Extending the SequenceType in Swift - swift

I wondered why map() and filter() in SequenceType return both an Array.
Actually, I don't think that's necessary. Returning a sequence again feels much more sensible to me.
However, I got stuck when trying to add sequential versions. Here's my attempt with map:
extension SequenceType {
func seqMap<T, S: SequenceType where S.Generator.Element == T>(
transform: Self.Generator.Element -> T) -> S
{
var sourceGen = generate()
let tGen: AnyGenerator<T> = anyGenerator {
if let el = sourceGen.next() {
return transform(el)
} else {
return nil
}
}
return AnySequence { tGen }
}
}
XCode tells me at the last return statement the following error:
cannot invoke initializer for type 'AnySequence<T>' with an argument list of type '(() -> AnyGenerator<T>)'
note: overloads for 'AnySequence<T>' exist with these partially matching parameter lists: (S), (() -> G)
Actually, my tGen is of type () -> G, so why does XCode think it is ambiguous?

The problem becomes more apparent if you split the return statement:
let tSeq = AnySequence { tGen }
return tSeq // error: cannot convert return expression of type 'AnySequence<T>' to return type 'S'
The compiler would infer the placeholder type S from the context
of a method call, and that could be any sequence
type with element type T, and not necessarily an AnySequence.
Here is a simple example demonstrating the same problem:
protocol MyProtocol { }
struct MyType { }
extension MyType : MyProtocol { }
func foo<P : Protocol>() -> P {
return MyType() // error: cannot convert return expression of type 'MyType' to return type 'P'
}
To solve the problem, change the return type to AnySequence<T>
and drop the generic type S:
extension SequenceType {
func seqMap<T>(transform: Self.Generator.Element -> T) -> AnySequence<T>
{
var sourceGen = generate()
let tGen: AnyGenerator<T> = anyGenerator {
if let el = sourceGen.next() {
return transform(el)
} else {
return nil
}
}
return AnySequence { tGen }
}
}
which can be written more compactly as
extension SequenceType {
func seqMap<T>(transform: Self.Generator.Element -> T) -> AnySequence<T>
{
var sourceGen = generate()
return AnySequence(anyGenerator {
sourceGen.next().map(transform)
})
}
}
using the map() method of the Optional type.
But note that SequenceType already has a lazy method which returns
a LazySequenceType:
/// A sequence containing the same elements as a `Base` sequence, but
/// on which some operations such as `map` and `filter` are
/// implemented lazily.
///
/// - See also: `LazySequenceType`
public struct LazySequence<Base : SequenceType>
and you can use
someSequence.lazy.map { ... }
to get a (lazily evaluated) sequence of the mapped values.

Related

Swift couldn't infer generic type when I was trying to provide my own implementation of AnySequence

The problem is when one protocol depends on another through its associated type, compiler isn't able to infer generic types.
So, I was playing around with Swift's type erasure technique trying to become familiar with its idea. Basically it'd been pretty understandable until I got to Sequence protocol. It's known that it has an associated type - Iterator, which conforms IteratorProtocol. That said, I've been trying to achieve similar behavior in my own implementation. That's what I've done:
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator<Element>: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
typealias Iterator = CustomAnyIterator<Element>
typealias Element = Iterator.Element
private let _makeIterator: () -> Iterator
init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator {
_makeIterator = sequence.makeIterator
}
func makeIterator() -> Iterator {
return _makeIterator()
}
}
let sequence = CustomAnySequence([1, 2, 3])
So, the last line gives the following error: Generic parameter 'Element' could not be inferred.
Then if I try to fix it by explicitly specifying Element type:
let sequence = CustomAnySequence<Int>([1, 2, 3])
it's not making it better. The next Xcode complaint is: Generic parameter 'S' could not be inferred.
So is there my fault, or it's just too much overhead for Swift's type inference?
Actually, I've run into another possible implementation - it's using private subclass wrapping. I don't really like it (that's why I was trying to do it on my own) because there are "fatal-error-must-be-subclassed" methods in superclass's implementations, which don't contribute to clean code. Also, I'm not sure how I could implement this functionality by the initializer of CustomAnySequence (I've only found it possible by making a static method). Despite all that, that's the code:
class CustomAnySequence<Element>: Sequence {
class Iterator: IteratorProtocol {
func next() -> Element? {
fatalError("Must be overriden")
}
}
func makeIterator() -> Iterator {
fatalError("Must be overriden")
}
}
private final class CustomAnySequenceImplementation<S: Sequence>: CustomAnySequence<S.Element> {
final class IteratorImplementation: Iterator {
var wrapped: S.Iterator
init(_ wrapped: S.Iterator) {
self.wrapped = wrapped
}
override func next() -> S.Element? {
return wrapped.next()
}
}
var sequence: S
init(_ sequence: S) {
self.sequence = sequence
}
override func makeIterator() -> IteratorImplementation {
return IteratorImplementation(sequence.makeIterator())
}
}
extension CustomAnySequence {
static func make<S: Sequence>(_ sequence: S) -> CustomAnySequence<Element> where S.Element == Element {
return CustomAnySequenceImplementation<S>(sequence)
}
}
func printInts(_ sequence: CustomAnySequence<Int>) {
for element in sequence {
print(element)
}
}
printInts(CustomAnySequence.make([1, 2, 3]))
printInts(CustomAnySequence.make(Set([4, 5, 6])))
It actually does work, but it looks a bit like a boilerplate. At least, if you realize how to improve it by using an initializer, please let me know. Thank you in advance!
The problem with the first implementation is that
let sequence = CustomAnySequence([1, 2, 3])
does not satisfy the constraint in
init<S: Sequence>(_ sequence: S) where S.Iterator == Iterator
[1, 2, 3] is a sequence, but its iterator type is not your CustomAnyIterator. What you really want is to pass a sequence with the same element type, not the same iterator type:
init<S: Sequence>(_ sequence: S) where S.Element == Element
and pass sequence.makeIterator() to the init method of CustomAnyIterator.
Note also the inner class can inherit the Element type placeholder from the outer class, and that the type aliases are not really needed.
final class CustomAnySequence<Element>: Sequence {
class CustomAnyIterator: IteratorProtocol {
private let _next: () -> Element?
init<I: IteratorProtocol>(_ iterator: I) where I.Element == Element {
var iterator = iterator
_next = { iterator.next() }
}
func next() -> Element? {
return _next()
}
}
private let _makeIterator: () -> CustomAnyIterator
init<S: Sequence>(_ sequence: S) where S.Element == Element {
_makeIterator = { CustomAnyIterator(sequence.makeIterator()) }
}
func makeIterator() -> CustomAnyIterator {
return _makeIterator()
}
}
You may also consider to use a struct instead of a class.

Generic tail in Swift

tail for array:
private extension Array {
var tail: Array { get { return Array(dropFirst(self)) } }
}
And here is generic version for Sliceable:
public func tail<S: Sliceable>(sequence: S, initializer: ((S.SubSlice) -> S)) -> S {
return initializer(dropFirst(sequence))
}
let s = tail("12", {String($0)})
Is it possible to rewrite generic tail without initializer arg?
I.e. call initializer via sequence type (S() or something)?
For a sliceable type T, T.SubSlice can be different from T.
For example String.SubSlice == String, but Array.SubSlice == ArraySlice<T>.
You can define a protocol which describes all types which can be
created from their own subslices:
public protocol CreatableFromSubslice : Sliceable {
init(_ subslice : Self.SubSlice)
}
Even if most (all?) built-in sliceable types can be created from their own
subslice, you still have to tell that the compiler with empty
extensions:
extension String : CreatableFromSubslice { }
extension Array : CreatableFromSubslice { }
// ...
Then tail() can be defined as
public func tail<S: CreatableFromSubslice>(slice: S) -> S {
return S(dropFirst(slice))
}
Example:
let s = tail("12")
println(s) // "2"
let a = tail([1, 2, 3])
println(a) // [2, 3]
For types which are equal to their subslice type you could define
public func tail<S: Sliceable where S.SubSlice == S >(slice: S) -> S {
return dropFirst(slice)
}
This can be applied to String, but not to Array.

Tuple-type in Swift generic constraint

I'm trying to write a generic function in Swift with the constraint that the parameter must be a sequence of pairs (which I'm going to turn into a dictionary). Is this possible? I've tried a number of variations on the following, but the compiler doesn't like any of them.
func foo<K, V, S: SequenceType where S.Generator.Element == (K,V)>(xs: S) { //...}
Not a direct answer to your question, but if you want to create
a dictionary then you could define your function as an extension
method to Dictionary and use the fact that Dictionary defines
typealias Element = (Key, Value)
Then your method declaration could be
extension Dictionary {
func foo<S : SequenceType where S.Generator.Element == Element>(xs : S) {
//...
}
}
To create a dictionary from the tuples, an init method might be more appropriate, for example
extension Dictionary {
init<S : SequenceType where S.Generator.Element == Element>(xs : S) {
self.init()
var gen = xs.generate()
while let (key, value) : Element = gen.next() {
self[key] = value
}
}
}
Usage:
let d = Dictionary(xs: [("a", 1), ("b", 2)])
println(d) // [b: 2, a: 1]
Note: The enumation via generate() and next() in above code
is a workaround for the problem that, for some reason
for (key, value) in xs { }
does not compile. Compare Implementing Set.addSequence in Swift.
Update: As of Swift 2/Xcode 7, the above method can be simplified
to
extension Dictionary {
init<S : SequenceType where S.Generator.Element == Element>(xs : S) {
self.init()
xs.forEach { (key, value) in
self[key] = value
}
}
}
It looks like a compiler bug to me.
Problem here is that: you cannot use tuple type directly in generic parameters.
As #MartinR said in his answer, it works if we use typealiased tuple type. But of course, we cannot declare generic typealias in global context.
For example, this compiles and works:
struct Foo<K,V> {
typealias Element = (K,V)
static func foo<S:SequenceType where S.Generator.Element == Element>(xs:S) {
var gen = xs.generate()
while let (k,v): Element = gen.next() {
println((k,v))
}
}
}
Foo.foo(["test":"foo", "bar": "baz"])
One more idea is something like this:
struct SequenceOfTuple<K,V>: SequenceType {
typealias Element = (K,V)
let _generate:() -> GeneratorOf<Element>
init<S:SequenceType where S.Generator.Element == Element>(_ seq:S) {
_generate = { GeneratorOf(seq.generate()) }
}
func generate() -> GeneratorOf<Element> {
return _generate()
}
}
func foo<K,V>(xs:SequenceOfTuple<K,V>) {
for (k, v) in xs {
println((k,v))
}
}
foo(SequenceOfTuple(["test":"foo", "bar": "baz"]))
In this case, you must wrap the sequence of tuple with SequenceOfTuple type, then pass it to foo().
Hmm...
You can use a struct with a subscript and store the results in a Dictionary:
struct Matrix<K:Hashable, V> {
var container:[K:[K:V]] = [:]
subscript(x:K, y:K) -> V? {
get {
return container[x]?[y]
}
set (value) {
if container[x] == nil {
container[x] = [:]
}
container[x]![y] = value
}
}
}
var matrix = Matrix<Int, String>()
matrix[11,42] = "Hello World"
println("(11,42): \(matrix[11,42])") // Optional("Hello World")
println("(1,3): \(matrix[1,3])") // nil

How to make a function operate on a Sequence of Optional values?

How does one specify that a function should operate on a sequence of optional values in Swift? For example, I want to make a function like this, which works for an Array of Optional values, for sequences.
// Given an array of optional values, return the first one with a value, if any
func firstValue<E>(ary: [E?]) -> E? {
for e in ary {
if let x = e {
return x
}
}
return nil
}
What I was hoping would work, but doesn't, because because there is no such thing as OptionalType):
func firstValue<C: SequenceType where C.Generator.Element: OptionalType>(seq: C) -> C.Generator.Element {
var g = seq.generate()
while let e = g.next() {
return e
}
return nil
}
Try this:
func firstValue<E, S: SequenceType where S.Generator.Element == Optional<E> >(seq: S) -> E? {
var g = seq.generate()
while let e:Optional<E> = g.next() {
if e != nil {
return e
}
}
return nil
}
let a:[Int?] = [nil,nil, 42, nil]
println(firstValue(a)) // -> 42 as Int?
I tested with Xcode Version 6.1.1 (6A2006) and Version 6.2 (6C86e)
Note
Without :Optional<E> in while condition, the compiler crashes.
And if we declare the function like this, the compiler clashes on some environment.
func firstValue<S: SequenceType, E where S.Generator.Element == Optional<E> > {
// ^^^^^^^^^^^^^^^^^^ replaced E and S
I think these are compiler bug. Please see the comments below.
There are two operations needed for the sequence elements:
Check if an element is nil or not, and
Create a nil value of the appropriate type as the default return value if nothing as was found.
For #2 we can use the fact that enum Optional conforms to the NilLiteralConvertible
protocol. For #1 I have defined a NilComparable protocol and made
enum Optional conform to it:
protocol NilComparable {
func isNil() -> Bool
}
extension Optional : NilComparable {
func isNil() -> Bool { return self == nil }
}
Now we can define a function for all sequences whose elements conform
to NilComparable and NilLiteralConvertible. All sequences of optionals
fall into this category:
func firstValue<C: SequenceType where
C.Generator.Element : NilComparable,
C.Generator.Element : NilLiteralConvertible
>(seq: C) -> C.Generator.Element {
var gen = seq.generate()
while let elem = gen.next() {
if !elem.isNil() {
return elem
}
}
return nil // Here NilLiteralConvertible is used.
}
Example:
let arr = [nil, nil, Optional(1), Optional(2)] // Type is [Optional<Int>]
println(firstValue(arr)) // Output: Optional(1)
Update: There is already a function
func !=<T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool
which compares any optional value with nil, so the above protocol can be simplified
to
protocol NilComparable {
func !=(lhs: Self, rhs: _OptionalNilComparisonType) -> Bool
}
extension Optional : NilComparable { } // Already conforming
Then we can write if elem != nil { ... } instead of if !elem.isNil() { ... }
in the function.
A possible disadvantage is that _OptionalNilComparisonType is not officially
documented.
Remark: I tried to declare the function as
func firstValue<C: SequenceType, E where C.Generator.Element == Optional<E> >(seq: C) -> E? {
// ...
}
but that actually caused the compiler to crash. I don't know if this should compile.

How to use a protocol with associative type as return value in Swift?

I'm trying to use a protocol with associated type as return value of a class func.
Another post here on stackoverflow is about the same question and based on this post's answer I tried the following:
// addArg takes a single Int argument and returns something,
// which is capable of adding a another Int argument
class OpWithNoArg {
func addArg<OP: OpWithOneArg where OP.ArgType == Int>(arg: Int) -> OP {
return OpWithOneArgImpl() // (1) error here !
}
}
// a protocol with associated type, which allows adding another
// argument of a not yet specified type
protocol OpWithOneArg {
typealias ArgType
func addAnotherArg(arg: ArgType)
}
// an implementation of the protocol above,
// which fixes the associated type to an Int
class OpWithOneArgImpl : OpWithOneArg {
typealias ArgType = Int
func addAnotherArg(arg: Int) {
// ...
}
}
The error in Xcode 7.0 Beta 4 on line marked with (1) is
cannot convert return expression of type 'OpWithOneArgImpl' to
expected return type 'OP'
If I change the return value to an optional and nil is returned, the sample compiles successfully:
// return null
class OpWithNoArg {
func addArg<OP: OpWithOneArg where OP.ArgType == Int>(arg: Int) -> OP? {
// return OpWithOneArgImpl()
return nil
}
}
Is this way of using a protocol with associative type as return value possible in swift, and if that's the case, how can the compiler error mentioned above be fixed?
Thanks in advance!
EDIT:
In Java, the code would be something like the following snippet. I try to find a way in Swift to achieve the same.
class C {
<T> P<T> f(T arg) {
return new PImpl();
}
}
interface P<S> {
void g(S arg);
}
class PImpl<S> implements P<S> {
PImpl() {}
public void g(S arg) {}
}
Not clear what you are trying to achieve, but imho the error stems from the fact that in your addArg function you define a generic type OP which should be typically used in the function's arguments and body.
Instead you return a non generic type trying to force it to be treated as a generic `OP.
A quick fix could be a force cast to OP of your return object:
return OpWithOneArgImpl() as !OP
but I wouldn't recommend it.
In your example your addArg will always return a OpWithOneArgImpl thus it could just be defined as a func addArg(arg: Int) -> OpWithOneArgImpl
Hope this helps.
EDIT:
Probably this is not what you're trying to achieve, but hope it can help
with a clearer explanation of what I intended above.
protocol OpWithOneArg {
typealias ArgType
func addAnotherArg(arg: ArgType)
init() // Must have a init with no argument
}
class OpWithOneArgImpl : OpWithOneArg {
typealias ArgType = Int
func addAnotherArg(arg: Int) {
// ...
}
required init() {
// init implementation
}
}
class OpWithNoArg {
func addArgWithOPType<OP: OpWithOneArg where OP.ArgType == Int>(op: OP.Type, arg: Int) -> OP {
return OP() // Here we use the init
}
}
let foo = OpWithNoArg()
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: 3)
Edit:
Maybe you might investigate the use of generic types:
protocol OpWithOneArg {
typealias ArgType
func addAnotherArg(arg: ArgType)
init() // Must have a init with no argument
}
class OpWithOneArgImpl<T> : OpWithOneArg { // Generic implementation confirming to protocol
typealias ArgType = T
func addAnotherArg(arg: T) {
// ...
}
required init() {
// init implementation
}
}
class OpWithNoArg {
func addArgWithOPType<OP: OpWithOneArg>(op: OP.Type, arg: OP.ArgType) -> OP {
return OP() // Here we use the init
}
}
let foo = OpWithNoArg()
// OpWithOneArgImpl<Int>
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: 3)
// OpWithOneArgImpl<String>
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: "Hello")