Suppose for example we're talking about elements of type Int (but the question still applies to any type)
I have some functionality which needs to loop over a sequence of Ints. But I don't care if behind the scenes this sequence is implemented as an Array, or a Set or any other exotic kind of structure, the only requirement is that we can loop over them.
Swift standard library defines the protocol SequenceType as "A type that can be iterated with a for...in loop". So my instinct is to define a protocol like this:
protocol HasSequenceOfInts {
var seq : SequenceType<Int> { get }
}
But this doesn't work. SequenceType is not a generic type which can be specialized, it's a protocol. Any particular SequenceType does have a specific type of element, but it's only available as an associated type: SequenceType.Generator.Element
So the question is:
How can we define a protocol which requires a specific type of sequence?
Here's some other things I've tried and why they aren't right:
Fail 1
protocol HasSequenceOfInts {
var seq : SequenceType { get }
}
Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements
Fail 2
protocol HasSequenceOfInts {
var seq : AnySequence<Int> { get }
}
class ArrayOfInts : HasSequenceOfInts {
var seq : [Int] = [0,1,2]
}
I thought this one would work, but when I tried a concrete implementation using an Array we get
Type 'ArrayOfInts' does not conform to protocol 'HasSequenceOfInts'
This is because Array is not AnySequence (to my surprise... my expectation was that AnySequence would match any sequence of Ints)
Fail 3
protocol HasSequenceOfInts {
typealias S : SequenceType
var seq : S { get }
}
Compiles, but there's no obligation that the elements of the sequence seq have type Int
Fail 4
protocol HasSequenceOfInts {
var seq : SequenceType where S.Generator.Element == Int
}
Can't use a where clause there
So now I'm totally out of ideas. I can easily just make my protocol require an Array of Int, but then I'm restricting the implementation for no good reason, and that feels very un-swift.
Update Success
See answer from @rob-napier which explains things very well. My Fail 2 was pretty close. Using AnySequence can work, but in your conforming class you need to make sure you convert from whatever kind of sequence you're using to AnySequence. For example:
protocol HasSequenceOfInts {
var seq : AnySequence<Int> { get }
}
class ArrayOfInts : HasSequenceOfInts {
var _seq : [Int] = [0,1,2]
var seq : AnySequence<Int> {
get {
return AnySequence(self._seq)
}
}
}