> Am 16.06.2016 um 17:36 schrieb Paul Cantrell <cantr...@pobox.com>: > >> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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? -Thorsten
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution