Sent from my iPhone

> On Jun 18, 2016, at 2:29 AM, Thorsten Seitz <[email protected]> wrote:
> 
> 
>>> Am 17.06.2016 um 16:11 schrieb Douglas Gregor <[email protected]>:
>>> 
>>> 
>>>> 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]>:
>>>>> 
>>>>> On Jun 16, 2016, at 8:29 AM, Thorsten Seitz via swift-evolution 
>>>>> <[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
> 
> Wildcards would work, too, e.g. in Java it looks like follows:
> List<Collection<?>> heterogeneousListOfCollections = new ArrayList<>();
> 
> List<Integer> intList = new ArrayList<>();
> Collections.addAll(intList, 1, 2, 3);
> 
> List<String> stringList = new ArrayList<>();
> Collections.addAll(stringList, "Hello", "Swift");
> 
> heterogeneousListOfCollections.add(intList);
> heterogeneousListOfCollections.add(stringList);

Having to add wildcards means yet another advanced generics feature. I suspect 
that we can make generalized existentials sufficiently accessible for all Swift 
programmers. Not so sure one could do that with generic protocols and wildcards 
(Java's experience with wildcards is not encouraging).

  - Doug

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to