> On 7 Feb 2017, at 06:18, Slava Pestov <[email protected]> wrote:
> 
>> 
>> On Feb 6, 2017, at 9:12 PM, Karl Wagner <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> 
>>> On 7 Feb 2017, at 06:05, Slava Pestov <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>>> 
>>>> On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution 
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> - Nested protocols in generic types are not parameterised by the parent's 
>>>> generic parameters.
>>> So if I write GenericType<Int>.SomeProto and GenericType<String>.SomeProto, 
>>> is it the same protocol? What about GenericType.SomeProto, is that allowed?
>>> 
>>> Slava
>> 
>> GenericType.SomeProto (without parameters) is the only spelling that is 
>> allowed. There is no GenericType<Int>.SomeProto.
>> 
>> That way we avoid every bound-generic type creating a new protocol. 
>> I think it works really nicely when you consider what it would like like 
>> with existential-based capturing. Notice that there is only one 
>> ‘MyCollectionView.Source’, and compatibility is determined based on 
>> existential constraints.
>> 
>> - Karl
>> 
>> 
>> class MyCollectionView<MediaItem> : UICollectionView {
>> 
>>     protocol Source {
>>         // [implicit] associatedtype MediaItem
> 
> I’m worried this is going to be tricky to implement; we definitely won’t get 
> this with the initial implementation of nested protocol types.

Do you mean that unparameterised protocols would be tricky to implement, or 
that capturing and implicit associated types would be? Because the latter isn’t 
part of the proposal - just sketching out how a capturing solution _might_ look.


> 
> 
>>         func item(at: Int) -> MediaItem
>>         var numberOfItems: Int { get }
>>     }
>>     var source: Any<MyCollectionView.Source where .MediaItem == MediaItem> 
>> // Not possible today.
> 
> I think for this use-case, it makes sense to allow the protocol itself to be 
> parametrized.

I used to think so, but your comments on the PR and working through some 
examples made me prefer this way. I think it’s exactly what we mean when we say 
that associated types are preferred to generic protocols. It also means that 
adding or removing generic types from the parent does not affect the nested 
protocol in any way - it could still be mangled the same for ABI compatibility 
and spelled the same for source compatibility.

The syntax is not exactly ideal. I’m using the Any<...> syntax because I think 
it’s a bit easier to understand in the context of this discussion, but that’s 
already gone from the language, so really it would look closer to:

var source: Source where .MediaItem == MediaItem

Still not ideal. But then, we automatically infer generic type parameters 
inside a generic context. Maybe it would be reasonable to do the same in this 
context?

extension Array where Element: Comparable {

var reverseSorted: Array {  //< inferred to be Array<T> by context
return self.sorted(by: >)
}
}

For capture-existentials, the analog may look something like:

var source: Source // [implicit] where .MediaItem == MediaItem, exhaustively 
binding all captured types. May be over-specific.

We would need a way to opt-out of that, though:

var source: Source where _ // Make the existential less specific with an 
explicit ‘where’ clause.

But none of that is part of the proposal. Again, just sketching what the 
situation might look like later if we took this approach. I’m curious to see 
what others feel about it.

- Karl

> 
> Slava
> 
>> }
>> 
>> class BookSource: MyCollectionView.Source {
>>     typealias MediaItem = Book
>> 
>>     func item(at: Int) -> Book { /* ... */ }
>>     var numberOfItems: Int     { /* ... */ }
>> }
>> 
>> class DummySource<MediaItem>: MyCollectionView.Source where MediaItem: 
>> DummyConstructable {
>>     // associatedtype 'MediaItem' bound to generic parameter.
>> 
>>     func item(at: Int) -> MediaItem { /* ... */ }
>>     var numberOfItems: Int          { /* ... */ } 
>> }
>> 
>> MyCollectionView<Book>().source = BookSource()
>> MyCollectionView<Book>().source = DummySource<Book>()
>> MyCollectionView<Song>().source  = DummySource() // type is: 
>> DummySource<Song>
>> MyCollectionView<Movie>().source = DummySource() // type is: 
>> DummySource<Movie>

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

Reply via email to