ambientlight ambientlight - 1 year ago 61
Swift Question

Swift: Any Kind of sequence as a function parameter

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

Something like this:

private func _addToCurrentTileset(tilesToAdd tiles: SequenceType)

Is there any way how I can do it?

It seems relatively straightforward, but I can't figure it out somehow. 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 will conform to SequenceType and the Self requirement from it.

I can eliminate the associatedType requirement with, but not Self:

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

Now if say I can eliminate self requirement, then already with such protocol definition other collectionType entities like arrays, sets won't conform to it.

my custom sequences are all subclasses of enumerator type defined as:

public class Enumerator<T> {

public func nextObject() -> T? {

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()

Answer Source

The compiler is telling you the answer: "Protocol 'SequenceType' can only be used as a generic constraint because it has Self or associated type requirements".

You can therefore do this with generics:

private func _addToCurrentTileset<T:SequenceType>(tilesToAdd tiles: T) {

This will allow you to pass in any concrete type that conforms to SequenceType into your function. Swift will infer the concrete type, allowing you to pass the sequence around without lose type information.

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

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

Or to a concrete type:

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

If you don't care about the concrete type of the sequence itself (useful for mixing them together and in some cases storing them), then Anton's answer has got you covered with the type-erased version.