Swift: any kind of sequence as a function parameter

I created my own type of sequence, and I want the function to accept any sequence as a parameter. (I want to use both sets and my sequence types on it)

Something like that:

private func _addToCurrentTileset(tilesToAdd tiles: SequenceType) 

Is there any way I can do this?

It seems relatively simple, but I just can't figure it out. The Swift toolchain tells me: Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements , and I don’t know how to create a protocol that matches SequenceType and the Self requirement from it.

I can exclude a related requirement like c, but not Self:

 protocol EnumerableTileSequence: SequenceType { associatedtype GeneratorType = geoBingAnCore.Generator associatedtype SubSequence: SequenceType = EnumerableTileSequence } 

Now, if I say that I can eliminate the requirement itself, then with such a protocol definition, other objects of type collectionType, such as arrays, sets will not match it.

Link: my user sequences are all subclasses of an enum type defined as:

 public class Enumerator<T> { public func nextObject() -> T? { RequiresConcreteImplementation() } } extension Enumerator { public var allObjects: [T] { return Array(self) } } extension Enumerator: SequenceType { public func generate() -> Generator<T> { return Generator(enumerator: self) } } public struct Generator<T>: GeneratorType { let enumerator: Enumerator<T> public mutating func next() -> T? { return enumerator.nextObject() } } 
+5
source share
2 answers

The compiler tells you the answer: "Protocol" Sequence "can only be used as a general restriction , since it has its own or related type requirements.

This way you can do this with generics:

 private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) { ... } 

This will allow you to pass any particular type matching Sequence into your function. Swift will output a specific type, allowing you to pass a sequence without losing type information.

If you want to limit the type of an element in a sequence to a given protocol, you can do:

 private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) where T.Element: SomeProtocol { ... } 

Or to a specific type:

 private func _addToCurrentTileset<T: Sequence>(tilesToAdd tiles: T) where T.Element == SomeConcreteType { ... } 

If you don’t care about the specific type of the sequence itself (useful for mixing them and in most cases storing them), then Anton received the answer that you covered the version of Sequence with the type of erasure.

+6
source

You can use type-eraser AnySequence for this:

Erase type sequence.

Passes operations to an arbitrary base sequence that has the same Element type, hiding the specifics of the underlying SequenceType .

eg. if you need to store the tiles as an internal property or somehow use your specific type in the structure of your object, then this will be the way to go.

If you just need to be able to use a sequence without having to save it (for example, just map on it), you can simply use generics (for example, @ originaluser2 suggests). For instance. you can get something like:

 private func _addToCurrentTileset<S: SequenceType where S.Generator.Element == Tile>(tilesToAdd tiles: S) { let typeErasedSequence = AnySequence(tiles) // Type == AnySequence<Tile> let originalSequence = tiles // Type == whatever type that conforms to SequenceType and has Tile as its Generator.Element } 
+4
source

All Articles