> On Jun 16, 2016, at 9:46 AM, Thorsten Seitz via swift-evolution
> <[email protected]> wrote:
>
>>
>> Am 16.06.2016 um 17:36 schrieb Paul Cantrell <[email protected]
>> <mailto:[email protected]>>:
>>
>>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> Protocols are a mechanism for deriving types from each other whereas
>>> generics are a way to parameterize types. My point was that Swift's other
>>> way to parameterize types, namely by associated types, is very similar to
>>> generics with wildcards when looking a the existentials of such protocols.
>>
>> This has been a point of confusion for me as well. I keep hearing that
>> associated types are different from generic protocols, but this seems like a
>> distinction without a difference.
>>
>> Suppose Swift allowed generic protocols. How would a hypothetical
>> Collection<Foo> be different in practice from the proposed existential
>> Any<Collection where .Element == Foo>?
>>
>> Yes, in the realm of type theory and compiler internals they might
>> represented differently, sure. But in practice, in terms of what code can
>> actually do? I know of only two differences:
>>
>> 1. A type can only conform to any given protocol with one set of type
>> parameters. (Nothing can be both Collection<Foo> and Collection<Bar>.)
>>
>> 2. When a type conforms to Collection, it declares “associatedtype Foo”
>> instead of “: Collection<Foo>”, and Foo can be inferred by the compiler in
>> some circumstances. That’s handy, but it’s a syntactic difference.
>
> That syntactic difference is *very* handy IMO for the following reason: with
> generics I have to repeat all types over and over again which gets ugly when
> I have levels of nesting where type parameters are constrained by other
> generics, which requires adding their parameters to the parameter list.
> Essentially the nested parameters have to be fully flattened because each
> type parameter has to be explicitly specified.
>
> I’ll try to show that with a simplified example:
>
> // with associated types
>
> protocol Edge {
> associatedtype VertexType
>
> var source: VertexType { get }
> var target: VertexType { get }
> }
>
> protocol Graph {
> associatedtype EdgeType : Edge
>
> var vertices: [EdgeType.VertexType] { get }
> var edges: [EdgeType] { get }
>
> func outEdges(vertex: EdgeType.VertexType) -> [EdgeType]
> }
>
> protocol GraphIterator {
> associatedtype GraphType : Graph
>
> var graph: GraphType { get }
>
> var startVertex: GraphType.VertexType { get }
>
> func enter(vertex: GraphType.VertexType)
> func propagate(along edge: GraphType.EdgeType)
> func finish(vertex: GraphType.VertexType)
> }
>
>
> // with generics
>
> class Edge<VertexType> {
> var source: VertexType
> var target: VertexType
> }
>
> class Graph<VertexType, EdgeType: Edge<VertexType>> {
>
> var vertices: [VertexType]
> var edges: [EdgeType]
>
> func outEdges(vertex: VertexType) -> [EdgeType]
>
> }
>
> class GraphIterator<VertexType, EdgeType: Edge<VertexType>, GraphType:
> Graph<VertexType, EdgeType>> {
>
> var graph: GraphType
>
> var startVertex: VertexType
>
> func enter(vertex: VertexType)
> func propagate(along edge: EdgeType)
> func finish(vertex: VertexType)
> }
>
> Note, how the parameter list for GraphIterator exploded, because I had to
> list each level of nested types down to the VertexType, whereas
> in the associated types example the GraphIterator simply declares an
> associated type conforming to the topmost type of my nesting, the Graph.
>
>
>>
>> Is there a deeper difference I’m missing?
>
> Maybe Dave can chime in here?
You can recover an associated type (say, X.Element) by just having the type
“X”, but this is not true for a type parameter. That doesn’t matter when you
have (or want to specify) that type… for example, your comment that
Collection<Foo> and Any<Collection where .Element == Foo> would basically be
the same thing.
However, with generalized/enhanced existentials you would be able to write
var heterogeneousArrayOfCollections: [Collection]
heterogeneousArrayOfCollections.append([1, 2 3])
heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 2])
You can’t do that with generic protocols, because there is no common element
type:
var heterogeneousArrayOfCollections: [Collection<???>]
One could perhaps try to rely on subtyping of collections for this specific case
var heterogeneousArrayOfCollections: [Collection<Any>]
heterogeneousArrayOfCollections.append([1, 2 3])
heterogeneousArrayOfCollections.append([“Hello” : 1, “Swift” : 2])
but that’s not something we have now and doesn’t really generalize well in
Swift.
- Doug
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution