Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function that accepts sequence of type

I want a function that accepts a sequence of Int. Here is what I want to write:

func process(items: Sequence<Int>) {
   items.forEach { ... }
}

Error: "Cannot specialize non-generic type 'Sequence'".

Corrected (I think):

func process<S: Sequence>(items: S) where S.Iterator.Element == Int {
    items.forEach { ... }
}

Quite a bit more verbose.

I know that the Sequence protocol has an associated type of Iterator which has Element. But I'm not quite sure why I have to resolve the Int requirement in such a weird way.

What are the underlying concepts that make the first version not work but the second? What does the error mean?

like image 578
tombardey Avatar asked Sep 26 '16 14:09

tombardey


1 Answers

Your question is to do with the difference between generic types and associated types. See here (sections titled "Generic Types", "Associated Types") for a basic explanation of their purposes in Swift. Protocols, like Sequence, use associated types, rather than generic types. Your first code sample would make sense if Sequence was a concrete class with a generic type - this difference should explain the error message.

As for why protocols use associated types, rather than generic types, see the top answer to this question. Essentially, though they seem to serve the same purpose, associated types are meant to be more flexible and descriptive, where generic types are about implementation. This makes your code sample more verbose, but overall, makes many code samples simpler.

In fact, from the Sequence source code, Sequence has an associated type Iterator, which conforms to the IteratorProtocol protocol, which in turn has its own associated type Element (which can be any type).

like image 62
Connor Neville Avatar answered Sep 30 '22 00:09

Connor Neville