Re: [swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-17 Thread Karl Wagner via swift-evolution
  
Anybody from core-team able to weigh in: do we want to keep this rule of not 
allowing parametrised protocols (in which case nesting is "trivial" - capturing 
is not allowed, only one protocol exists, so it's just namespacing), or is this 
something which should be deferred?
  
  
  

  
If possible I would like to include protocols inside of generic types. I kind 
of like the non-parameterised version. It's elegant and allows you to write 
generic conformers to the protocol.
  
  

  
  
>   
> On Feb 7, 2017 at 4:10 pm,  mailto:matt...@anandabits.com)> 
>  wrote:
>   
>   
>   
>   
>   
> >   
> > On Feb 6, 2017, at 11:12 PM, Karl Wagner via swift-evolution  
> >   wrote:
> >   
> >   
> > 
> >
> >   
> >   
> > >   
> > > On 7 Feb 2017, at 06:05, Slava Pestov   > > (mailto:spes...@apple.com)>  wrote:
> > >   
> > >   
> > >   
> > > >   
> > > >
> > > >  On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution  
> > > >   wrote:  
> > > >  
> > > >   
> > > >   
> > > >  - Nested protocols in generic types are not parameterised by the 
> > > > parent's generic parameters.  
> > > >
> > > >   
> > > >   
> > >   
> > > So if I write GenericType.SomeProto and 
> > > GenericType.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.SomeProto.
> >   
> >
> >   
> > That way we avoid every bound-generic type creating a new protocol.   
> >   
> >   
> >   
>   
>
>   
> I have only had a chance to scan the proposal so I will probably have more 
> comments after I take a closer look, but I want to respond to this topic 
> right away.
>   
>
>   
> I understand the reason why you want it to work this way, but think it will 
> be a significant source of confusion.Protocols will behave differently 
> than any other entity nested in a generic type.This means the protocols 
> nested in generic types will likely be counterintuitive for most people.
>   
>
>   
> I know this was the case for me while I was scanning the proposal.I had 
> to think carefully to understand how you want this to work and why you want 
> this behavior.That is despite it being a relatively direct consequence of 
> the Swift’s design for protocols, which uses associated types and 
> intentionally does not allow generic protocols.
>   
>
>   
> It may be that there isn’t a good way to avoid that and we need to try to 
> address it through documentation and education.But I think this should 
> receive careful consideration before we commit to this direction.
>   
>
>   
> Overall the proposal looks really great!I’m really looking forward to 
> this feature.
>   
>   
> >   
> >   
> >   
> > 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  :  UICollectionView  {  protocol   
> > Source  {  //  [implicit] associatedtype MediaItem func   item(at:  
> > Int)  ->  MediaItem  var  numberOfItems:   Int  {  get  } }  var  source:   
> > Any   //  Not 
> > possible today.   }  class   BookSource:  MyCollectionView.Source  {  
> > typealias   MediaItem   =  Book  func   item(at:  Int)  ->  Book {  /*  ... 
> >  */  }  var  numberOfItems:   Int  {  /*  ...  */  } }  class   
> > DummySource:  MyCollectionView.Source  where  MediaItem:   
> > DummyConstructable  {  //  associatedtype 'MediaItem' bound to generic 
> > parameter. func   item(at:  Int)  ->  MediaItem {  /*  ...  */  }  var  
> > numberOfItems:   Int  {  /*  ...  */  } } MyCollectionView().source   
> > =   BookSource() MyCollectionView().source   =  DummySource() 
> > MyCollectionView().source   =   DummySource()  //  type is: 
> > DummySource   MyCollectionView().source   =   DummySource()  
> > //  type is: DummySource   
> >   
> >
> > 
> >
> >   
> >
> >___
> >  swift-evolution mailing list
> >   swift-evolution@swift.org (mailto:swift-evolution@swift.org)
> >  https://lists.swift.org/mailman/listinfo  ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-07 Thread Matthew Johnson via swift-evolution

> On Feb 6, 2017, at 11:12 PM, Karl Wagner via swift-evolution 
>  wrote:
> 
> 
>> On 7 Feb 2017, at 06:05, Slava Pestov > > wrote:
>> 
>>> 
>>> On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution 
>>> > wrote:
>>> - Nested protocols in generic types are not parameterised by the parent's 
>>> generic parameters.
>> So if I write GenericType.SomeProto and GenericType.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.SomeProto.
> 
> That way we avoid every bound-generic type creating a new protocol. 

I have only had a chance to scan the proposal so I will probably have more 
comments after I take a closer look, but I want to respond to this topic right 
away.

I understand the reason why you want it to work this way, but think it will be 
a significant source of confusion.  Protocols will behave differently than any 
other entity nested in a generic type.  This means the protocols nested in 
generic types will likely be counterintuitive for most people.  

I know this was the case for me while I was scanning the proposal.  I had to 
think carefully to understand how you want this to work and why you want this 
behavior.  That is despite it being a relatively direct consequence of the 
Swift’s design for protocols, which uses associated types and intentionally 
does not allow generic protocols.

It may be that there isn’t a good way to avoid that and we need to try to 
address it through documentation and education.  But I think this should 
receive careful consideration before we commit to this direction.

Overall the proposal looks really great!  I’m really looking forward to this 
feature.  

> 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 : UICollectionView {
> 
> protocol Source {
> // [implicit] associatedtype MediaItem
> func item(at: Int) -> MediaItem
> var numberOfItems: Int { get }
> }
> var source: Any // 
> Not possible today.
> }
> 
> class BookSource: MyCollectionView.Source {
> typealias MediaItem = Book
> 
> func item(at: Int) -> Book { /* ... */ }
> var numberOfItems: Int { /* ... */ }
> }
> 
> class DummySource: MyCollectionView.Source where MediaItem: 
> DummyConstructable {
> // associatedtype 'MediaItem' bound to generic parameter.
> 
> func item(at: Int) -> MediaItem { /* ... */ }
> var numberOfItems: Int  { /* ... */ } 
> }
> 
> MyCollectionView().source = BookSource()
> MyCollectionView().source = DummySource()
> MyCollectionView().source  = DummySource() // type is: DummySource
> MyCollectionView().source = DummySource() // type is: 
> DummySource
> 
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-06 Thread Slava Pestov via swift-evolution

> On Feb 6, 2017, at 9:12 PM, Karl Wagner  wrote:
> 
> 
>> On 7 Feb 2017, at 06:05, Slava Pestov > > wrote:
>> 
>>> 
>>> On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution 
>>> > wrote:
>>> - Nested protocols in generic types are not parameterised by the parent's 
>>> generic parameters.
>> So if I write GenericType.SomeProto and GenericType.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.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 : 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.


> func item(at: Int) -> MediaItem
> var numberOfItems: Int { get }
> }
> var source: Any // 
> Not possible today.

I think for this use-case, it makes sense to allow the protocol itself to be 
parametrized.

Slava

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

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-06 Thread Karl Wagner via swift-evolution

> On 7 Feb 2017, at 06:05, Slava Pestov  wrote:
> 
>> 
>> On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution 
>> > wrote:
>> - Nested protocols in generic types are not parameterised by the parent's 
>> generic parameters.
> So if I write GenericType.SomeProto and GenericType.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.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 : UICollectionView {

protocol Source {
// [implicit] associatedtype MediaItem
func item(at: Int) -> MediaItem
var numberOfItems: Int { get }
}
var source: Any // 
Not possible today.
}

class BookSource: MyCollectionView.Source {
typealias MediaItem = Book

func item(at: Int) -> Book { /* ... */ }
var numberOfItems: Int { /* ... */ }
}

class DummySource: MyCollectionView.Source where MediaItem: 
DummyConstructable {
// associatedtype 'MediaItem' bound to generic parameter.

func item(at: Int) -> MediaItem { /* ... */ }
var numberOfItems: Int  { /* ... */ } 
}

MyCollectionView().source = BookSource()
MyCollectionView().source = DummySource()
MyCollectionView().source  = DummySource() // type is: DummySource
MyCollectionView().source = DummySource() // type is: DummySource



___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-06 Thread Slava Pestov via swift-evolution

> On Feb 6, 2017, at 9:00 PM, Karl Wagner via swift-evolution 
>  wrote:
> - Nested protocols in generic types are not parameterised by the parent's 
> generic parameters.
So if I write GenericType.SomeProto and GenericType.SomeProto, is 
it the same protocol? What about GenericType.SomeProto, is that allowed?

Slava

> - Some observations as to how capturing might be implemented in the future, 
> standard library benefits.
> 
> This is a chance for everybody to go over it once more before the actual 
> review.
> 
> Github: https://github.com/apple/swift-evolution/pull/552 
> 
> Raw:
> 
> # Ease restrictions on protocol nesting
> 
> * Proposal: [SE-](-ease-protocol-nesting.md)
> * Authors: [Karl Wagner](https://github.com/karlwa 
> )
> * Review Manager: TBD
> * Status: **Awaiting review**
> 
> *During the review process, add the following fields as needed:*
> 
> * Decision Notes: 
> [Rationale](https://lists.swift.org/pipermail/swift-evolution/ 
> ), [Additional 
> Commentary](https://lists.swift.org/pipermail/swift-evolution/ 
> )
> * Bugs: [SR-](https://bugs.swift.org/browse/SR- 
> ), 
> [SR-](https://bugs.swift.org/browse/SR- 
> )
> * Previous Revision: 
> [1](https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/-filename.md
>  
> )
> * Previous Proposal: [SE-](-filename.md)
> 
> ## Introduction
> 
> Protocols define a way to express a syntactic and semantic contract. This 
> semantic nature means that protocols are often intended to used in the 
> context of one specific type (such as a 'delegate' protocol). Similarly, 
> protocols sometimes wish to define specific types to be used within the 
> context of that protocol (usually an `enum`).
> 
> This proposal would allow protocols to be nested in other types (including 
> other protocols), and for structural types to be nested inside of protocols 
> -- subject to a few constraints.
> 
> Swift-evolution thread: [Discussion thread topic for that 
> proposal](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161017/028112.html
>  
> )
> 
> ## Motivation
> 
> Nesting types inside other types allows us to scope their usage and provide a 
> cleaner interface. Protocols are an important part of Swift, and many popular 
> patterns (for example, the delegate pattern) define protocols which are 
> intended to be used in the semantic context of other types. It would be nice 
> to apply type-nesting here: `MyClass.Delegate` reads better than 
> `MyClassDelegate`, and literally brings structure to large frameworks.
> 
> Similarly, we have examples of protocols in the standard library which define 
> supporting types to be used in the context of that protocol - 
> `FloatingPointClassification`, `FloatingPointSign`, and 
> `FloatingPointRoundingRule` are enums which are used by various members of 
> the `FloatingPoint` protocol. These types are part of the contract which the 
> protocol defines, and so it would be nice if they could be nested within the 
> protocol to reflect that (i.e. `FloatingPoint.Classification`, 
> `FloatingPoint.Sign`, `FloatingPoint.RoundingRule`).
> 
> ## Proposed solution
> 
> The first part is to allow protocols to be nested inside of structural types 
> (for example, in the delegate pattern):
> 
> ```swift
> class AView {// A regular-old class
> protocol Delegate: class {   // A nested protocol
> func somethingHappened()
> }
> weak var delegate: Delegate?
> }
> 
> class MyDelegate: AView.Delegate {
> func somethingHappened() { /* ... */ }
> }
> ```
> 
> The second part is to allow nominal types to be nested inside of protocols 
> (for example, `FloatingPoint.Sign`).
> 
> ```swift
> protocol FloatingPoint {  
> // 'Sign' is required for conformance, therefore good candidate for 
> nesting.
> enum Sign {
> case plus
> case minus
> }
> var sign: Sign { get }
> }
> ```
> 
> Similarly, protocols may be nested inside other protocols:
> 
> ```swift
> protocol Scrollable: class { // A regular-old protocol.
> var currentPosition: Position { get }
> 
> protocol Delegate: class {   // A nested protocol.
> func scrollableDidScroll(_: Scrollable, from: Position)
> }
> weak var delegate: Delegate?
> }
> 
> class MyScrollable: Scrollable {
> var currentPosition = Position.zero
> 
> weak var delegate: Delegate?
> }
> 
> extension MyController: Scrollable.Delegate {
> func scrollableDidScroll(_ 

[swift-evolution] [RFC][Proposal] Ease restrictions on protocol nesting

2017-02-06 Thread Karl Wagner via swift-evolution
The proposal has been refined since the previous discussions. In particular:

- No capturing is allowed between nested types (beyond what already exists for 
nested generics).
- Access control for nested types in protocols.
- Nested types in constrained protocol extensions mean the same as in 
unconstrained extensions.
- Nested protocols in generic types are not parameterised by the parent's 
generic parameters.
- Some observations as to how capturing might be implemented in the future, 
standard library benefits.

This is a chance for everybody to go over it once more before the actual review.

Github: https://github.com/apple/swift-evolution/pull/552 

Raw:

# Ease restrictions on protocol nesting

* Proposal: [SE-](-ease-protocol-nesting.md)
* Authors: [Karl Wagner](https://github.com/karlwa)
* Review Manager: TBD
* Status: **Awaiting review**

*During the review process, add the following fields as needed:*

* Decision Notes: 
[Rationale](https://lists.swift.org/pipermail/swift-evolution/), [Additional 
Commentary](https://lists.swift.org/pipermail/swift-evolution/)
* Bugs: [SR-](https://bugs.swift.org/browse/SR-), 
[SR-](https://bugs.swift.org/browse/SR-)
* Previous Revision: 
[1](https://github.com/apple/swift-evolution/blob/...commit-ID.../proposals/-filename.md)
* Previous Proposal: [SE-](-filename.md)

## Introduction

Protocols define a way to express a syntactic and semantic contract. This 
semantic nature means that protocols are often intended to used in the context 
of one specific type (such as a 'delegate' protocol). Similarly, protocols 
sometimes wish to define specific types to be used within the context of that 
protocol (usually an `enum`).

This proposal would allow protocols to be nested in other types (including 
other protocols), and for structural types to be nested inside of protocols -- 
subject to a few constraints.

Swift-evolution thread: [Discussion thread topic for that 
proposal](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161017/028112.html)

## Motivation

Nesting types inside other types allows us to scope their usage and provide a 
cleaner interface. Protocols are an important part of Swift, and many popular 
patterns (for example, the delegate pattern) define protocols which are 
intended to be used in the semantic context of other types. It would be nice to 
apply type-nesting here: `MyClass.Delegate` reads better than 
`MyClassDelegate`, and literally brings structure to large frameworks.

Similarly, we have examples of protocols in the standard library which define 
supporting types to be used in the context of that protocol - 
`FloatingPointClassification`, `FloatingPointSign`, and 
`FloatingPointRoundingRule` are enums which are used by various members of the 
`FloatingPoint` protocol. These types are part of the contract which the 
protocol defines, and so it would be nice if they could be nested within the 
protocol to reflect that (i.e. `FloatingPoint.Classification`, 
`FloatingPoint.Sign`, `FloatingPoint.RoundingRule`).

## Proposed solution

The first part is to allow protocols to be nested inside of structural types 
(for example, in the delegate pattern):

```swift
class AView {// A regular-old class
protocol Delegate: class {   // A nested protocol
func somethingHappened()
}
weak var delegate: Delegate?
}

class MyDelegate: AView.Delegate {
func somethingHappened() { /* ... */ }
}
```

The second part is to allow nominal types to be nested inside of protocols (for 
example, `FloatingPoint.Sign`).

```swift
protocol FloatingPoint {  
// 'Sign' is required for conformance, therefore good candidate for nesting.
enum Sign {
case plus
case minus
}
var sign: Sign { get }
}
```

Similarly, protocols may be nested inside other protocols:

```swift
protocol Scrollable: class { // A regular-old protocol.
var currentPosition: Position { get }

protocol Delegate: class {   // A nested protocol.
func scrollableDidScroll(_: Scrollable, from: Position)
}
weak var delegate: Delegate?
}

class MyScrollable: Scrollable {
var currentPosition = Position.zero

weak var delegate: Delegate?
}

extension MyController: Scrollable.Delegate {
func scrollableDidScroll(_ scrollable: Scrollable, from: Position) { 
let displacement = scrollable.currentPosition.x - from.x
// ...
}
}
```

**Namespacing:**

It is important to draw a distinction between a protocol's nested types and its 
associated types. Associated types are placeholders (similar to generic type 
parameters), to be defined individually by each type which conforms to the 
protocol (e.g. every `Collection` will have a unique type of `Element`). Nested 
types are standard nominal types, and they don't neccessarily have anything to 
do with the conforming type (e.g.