Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Tino Heth via swift-evolution

> I don’t want this thread to get distracted with memberwise initialization
Makes sense in general, but Kotlin solves those problems as a whole, and the 
major benefit of their approach is that everything fits together really fine.
But I'll skip everything that is not related to forwarding.

> One approach I considered would look like this:
> 
> class Forwarder: P {
> // I didn’t like `implements` but didn’t have a better idea before I 
> abandoned this approach
> var forwardee: Forwardee implements P 
> }
Honestly, I'm can't see the value this discarded variant has for this 
discussion… you have to pit your proposal against Kotlin if you really want to 
convince anyone of its superiority.

> With the memberwise initialization proposal you also have the initializer 
> synthesized automatically.  The only thing it doesn’t do that your Kotlin 
> example does is automatically declare conformance.  This was an intentional 
> design decision because it allows for additional expressivity.  This is 
> addressed in the alternatives considered section of the proposal.  
Can you be more precise? Kotlin clearly states what a class is doing in its 
first line, with all expressivity that is necessary by practical means.

> Another difference that is maybe subtle but I think important is that with 
> the approach I considered forwarding is declared in the body of a type or 
> extension which emphasizes the fact that forwarding is an implementation 
> detail, not something users of the type should be concerned with.
But what is the benefit of this emphasis? No solution requires to make the 
details visible in the public interface, and the ability to bury an important 
thing like protocol conformance somewhere in the class implementation is no 
advantage for me.

> This approach was abandoned as it leads to problems in expressivity and 
> clarity.  Please see alternatives considered for an elaboration of that.  
> This is especially true with the new approach to handling Self values that 
> Brent suggested.  That approach requires additional syntax around the 
> forwarding declaration, but adds both clarity and expressiveness.
I think there is little need to worry about expressiveness for a feature that 
most potential users will probably never utilize in real code — and I don't 
think options like not conforming to a protocol that is forwarded is a big win 
here. It looks to me like you are optimizing for very uncommon cases, and 
sacrificing ease of use in the situations that are the most common by far.

> It appears to me that you value conciseness very highly.  I do value 
> conciseness but I also value safety, clarity, and expressiveness.  
No, I value elegance and simplicity  — they often lead to clarity and safety.

>> Why not simply make this feature syntactic sugar and just auto-generate the 
>> forwarding methods?
> 
> That is exactly what this proposal does.  Why do you feel it is not doing 
> that?
you're right, guess I mixed up the proposal with something else; so at least we 
agree on how it should work ;-)

I'm not saying Swift has to copy another language, but I doubt that anyone who 
knows Kotlin would actually consider to drop their solution in favor of what is 
currently discussed...

Tino

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Matthew Johnson via swift-evolution

> On Dec 31, 2015, at 11:18 AM, Dave Abrahams  wrote:
> 
>> 
>> On Dec 31, 2015, at 9:01 AM, Matthew Johnson > > wrote:
>> 
>> 
>> 
>> Sent from my iPad
>> 
>> On Dec 31, 2015, at 10:09 AM, Dave Abrahams > > wrote:
>> 
>>> 
>>> -Dave
>>> 
 On Dec 31, 2015, at 7:33 AM, Matthew Johnson via swift-evolution 
 > wrote:
 
> 
> On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de > 
> wrote:
> 
> 
>> I don’t want this thread to get distracted with memberwise initialization
> Makes sense in general, but Kotlin solves those problems as a whole, and 
> the major benefit of their approach is that everything fits together 
> really fine.
> But I'll skip everything that is not related to forwarding.
> 
>> One approach I considered would look like this:
>> 
>> class Forwarder: P {
>>// I didn’t like `implements` but didn’t have a better idea before I 
>> abandoned this approach
>>var forwardee: Forwardee implements P 
>> }
> Honestly, I'm can't see the value this discarded variant has for this 
> discussion… you have to pit your proposal against Kotlin if you really 
> want to convince anyone of its superiority.
> 
>> With the memberwise initialization proposal you also have the 
>> initializer synthesized automatically.  The only thing it doesn’t do 
>> that your Kotlin example does is automatically declare conformance.  
>> This was an intentional design decision because it allows for additional 
>> expressivity.  This is addressed in the alternatives considered section 
>> of the proposal.  
> Can you be more precise? Kotlin clearly states what a class is doing in 
> its first line, with all expressivity that is necessary by practical 
> means.
 
 What I mean is this.  In the example you gave and the syntax Kotlin uses:
 
 classs Forwarder(forwardee: Forwardee): P by forwardee {}
 
 Forwarding is coupled to protocol conformance.  This means I cannot use 
 forwarding without conforming to the protocol that is forwarded.  
 
 Here is a quick example using the syntax of my proposal to demonstrate the 
 difference:
 
 class Forwarder {
   let forwardee: Forwardee
   forward P to forwardee
 }
 
 vs
 
 class Forwarder: P {
   let forwardee: Forwardee
   forward P to forwardee
 }
 
 In the first example Forwarder does not conform to P.  Forwarding is only 
 used to synthesize the members of P.  I am greatly expanding the 
 motivation section of the proposal and will have examples showing where 
 this is what you want.  The lazy collections section I posted last night 
 includes the first examples where this is the case.
 
 In the second example here Forwarder does conform to P.  The author of 
 Forwarder has the flexibility to specify whether conformance is desired or 
 not.
>>> 
>>> There are ways to handle that, including factoring the APIs of interest out 
>>> of P and into a private protocol Q, then declaring the Forwardee’s 
>>> conformance to Q.  Now, there’s an expressivity problem with our current 
>>> access control system that you can’t use an internal or private protocol to 
>>> provide public API, but that should be fixed separately.
>> 
>> I'm not sure where Q comes into play in this specific example.  The idea 
>> here is that forwarding implementations of all members of P are synthesized 
>> by the forward declaration.  It is left up to Forwarder to decide whether or 
>> not to declare actual conformance to P.  I am also confused by "then 
>> declaring the Forwardee’s conformance to Q" because we are discussing 
>> Forwarder's conformance here, not Forwardee’s.
> 
> Presumably both ends of the forwarding arrangement would have to conform to 
> the same protocol, no?

No.  This is addressed in the proposal and the lazy collections motivating 
example I replied with last night.  I don’t think it’s a good idea to require 
this.

The forwardee needs to implement the members of the protocol but does not need 
to conform.  The forwarder will receive forwarding implementations of the 
members, but again does not need to declare conformance.  Forwarding is 
orthogonal to conformance, just as it is today when you manually write 
forwarding members today.

> 
>> What do you have in mind when you mention using a private or internal 
>> protocol to provide public API?  It sounds like that might be interesting 
>> but I'm having trouble imagining what the syntax would look like and exactly 
>> how it would work.  Is this something that is planned?  
> 
> Not planned, but desired.
> 
>> What might it look like?
> 
> Details need to be worked out.  

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Dave Abrahams via swift-evolution

> On Dec 31, 2015, at 9:01 AM, Matthew Johnson  wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Dec 31, 2015, at 10:09 AM, Dave Abrahams  > wrote:
> 
>> 
>> -Dave
>> 
>>> On Dec 31, 2015, at 7:33 AM, Matthew Johnson via swift-evolution 
>>> > wrote:
>>> 
 
 On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de > 
 wrote:
 
 
> I don’t want this thread to get distracted with memberwise initialization
 Makes sense in general, but Kotlin solves those problems as a whole, and 
 the major benefit of their approach is that everything fits together 
 really fine.
 But I'll skip everything that is not related to forwarding.
 
> One approach I considered would look like this:
> 
> class Forwarder: P {
>// I didn’t like `implements` but didn’t have a better idea before I 
> abandoned this approach
>var forwardee: Forwardee implements P 
> }
 Honestly, I'm can't see the value this discarded variant has for this 
 discussion… you have to pit your proposal against Kotlin if you really 
 want to convince anyone of its superiority.
 
> With the memberwise initialization proposal you also have the initializer 
> synthesized automatically.  The only thing it doesn’t do that your Kotlin 
> example does is automatically declare conformance.  This was an 
> intentional design decision because it allows for additional 
> expressivity.  This is addressed in the alternatives considered section 
> of the proposal.  
 Can you be more precise? Kotlin clearly states what a class is doing in 
 its first line, with all expressivity that is necessary by practical means.
>>> 
>>> What I mean is this.  In the example you gave and the syntax Kotlin uses:
>>> 
>>> classs Forwarder(forwardee: Forwardee): P by forwardee {}
>>> 
>>> Forwarding is coupled to protocol conformance.  This means I cannot use 
>>> forwarding without conforming to the protocol that is forwarded.  
>>> 
>>> Here is a quick example using the syntax of my proposal to demonstrate the 
>>> difference:
>>> 
>>> class Forwarder {
>>>   let forwardee: Forwardee
>>>   forward P to forwardee
>>> }
>>> 
>>> vs
>>> 
>>> class Forwarder: P {
>>>   let forwardee: Forwardee
>>>   forward P to forwardee
>>> }
>>> 
>>> In the first example Forwarder does not conform to P.  Forwarding is only 
>>> used to synthesize the members of P.  I am greatly expanding the motivation 
>>> section of the proposal and will have examples showing where this is what 
>>> you want.  The lazy collections section I posted last night includes the 
>>> first examples where this is the case.
>>> 
>>> In the second example here Forwarder does conform to P.  The author of 
>>> Forwarder has the flexibility to specify whether conformance is desired or 
>>> not.
>> 
>> There are ways to handle that, including factoring the APIs of interest out 
>> of P and into a private protocol Q, then declaring the Forwardee’s 
>> conformance to Q.  Now, there’s an expressivity problem with our current 
>> access control system that you can’t use an internal or private protocol to 
>> provide public API, but that should be fixed separately.
> 
> I'm not sure where Q comes into play in this specific example.  The idea here 
> is that forwarding implementations of all members of P are synthesized by the 
> forward declaration.  It is left up to Forwarder to decide whether or not to 
> declare actual conformance to P.  I am also confused by "then declaring the 
> Forwardee’s conformance to Q" because we are discussing Forwarder's 
> conformance here, not Forwardee’s.

Presumably both ends of the forwarding arrangement would have to conform to the 
same protocol, no?

> What do you have in mind when you mention using a private or internal 
> protocol to provide public API?  It sounds like that might be interesting but 
> I'm having trouble imagining what the syntax would look like and exactly how 
> it would work.  Is this something that is planned?  

Not planned, but desired.

> What might it look like?

Details need to be worked out.  One thing we were doing for a while in the 
stdlib, before the rules got tightened and made it impossible, was

struct X : PublicProtocol, PrivateProtocol {
   ...
}

extension PublicProtocol where Self : PrivateProtocol {
   // API that uses only PublicProtocol in its implementation here
}

> In any case, I don't see why that is related to requiring a Forwarder to 
> conform to the forwarded protocol.  There doesn't appear to me to be a good 
> reason to require that and there are reasons not to require it.  Protocols 
> enable and drive the forwarding member synthesis mechanism but that mechanism 
> doesn't need to require or provide conformance.  It is a third major way to 
> use protocols in addition to generic 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread David Owens II via swift-evolution

> On Dec 31, 2015, at 9:47 AM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> No.  This is addressed in the proposal and the lazy collections motivating 
> example I replied with last night.  I don’t think it’s a good idea to require 
> this.

Can you put your proposal on GitHub under your swift-evolution fork? It’s 
really hard to follow the current state of the proposal and the changes over 
time.


> The forwardee needs to implement the members of the protocol but does not 
> need to conform.  The forwarder will receive forwarding implementations of 
> the members, but again does not need to declare conformance.  Forwarding is 
> orthogonal to conformance, just as it is today when you manually write 
> forwarding members today.

I cannot think of a time where I wanted this pseudo-conformance. The entire 
purpose of forwarding, that I’ve ever wanted or seen at least, is to act as a 
pass-through from the outer type’s conformance to a protocol to an internal 
specific implementor of that protocol without having to write all of the 
boiler-plate code to make that happen.

So I find it confusing that you say they are orthogonal.

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Dave Abrahams via swift-evolution

> On Dec 31, 2015, at 9:47 AM, Matthew Johnson  wrote:
> 
>> 
>> On Dec 31, 2015, at 11:18 AM, Dave Abrahams > > wrote:
>> 
>>> 
>>> On Dec 31, 2015, at 9:01 AM, Matthew Johnson >> > wrote:
>>> 
>>> 
>>> 
>>> Sent from my iPad
>>> 
>>> On Dec 31, 2015, at 10:09 AM, Dave Abrahams >> > wrote:
>>> 
 
 -Dave
 
> On Dec 31, 2015, at 7:33 AM, Matthew Johnson via swift-evolution 
> > wrote:
> 
>> 
>> On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de 
>> > wrote:
>> 
>> 
>>> I don’t want this thread to get distracted with memberwise 
>>> initialization
>> Makes sense in general, but Kotlin solves those problems as a whole, and 
>> the major benefit of their approach is that everything fits together 
>> really fine.
>> But I'll skip everything that is not related to forwarding.
>> 
>>> One approach I considered would look like this:
>>> 
>>> class Forwarder: P {
>>>// I didn’t like `implements` but didn’t have a better idea before I 
>>> abandoned this approach
>>>var forwardee: Forwardee implements P 
>>> }
>> Honestly, I'm can't see the value this discarded variant has for this 
>> discussion… you have to pit your proposal against Kotlin if you really 
>> want to convince anyone of its superiority.
>> 
>>> With the memberwise initialization proposal you also have the 
>>> initializer synthesized automatically.  The only thing it doesn’t do 
>>> that your Kotlin example does is automatically declare conformance.  
>>> This was an intentional design decision because it allows for 
>>> additional expressivity.  This is addressed in the alternatives 
>>> considered section of the proposal.  
>> Can you be more precise? Kotlin clearly states what a class is doing in 
>> its first line, with all expressivity that is necessary by practical 
>> means.
> 
> What I mean is this.  In the example you gave and the syntax Kotlin uses:
> 
> classs Forwarder(forwardee: Forwardee): P by forwardee {}
> 
> Forwarding is coupled to protocol conformance.  This means I cannot use 
> forwarding without conforming to the protocol that is forwarded.  
> 
> Here is a quick example using the syntax of my proposal to demonstrate 
> the difference:
> 
> class Forwarder {
>   let forwardee: Forwardee
>   forward P to forwardee
> }
> 
> vs
> 
> class Forwarder: P {
>   let forwardee: Forwardee
>   forward P to forwardee
> }
> 
> In the first example Forwarder does not conform to P.  Forwarding is only 
> used to synthesize the members of P.  I am greatly expanding the 
> motivation section of the proposal and will have examples showing where 
> this is what you want.  The lazy collections section I posted last night 
> includes the first examples where this is the case.
> 
> In the second example here Forwarder does conform to P.  The author of 
> Forwarder has the flexibility to specify whether conformance is desired 
> or not.
 
 There are ways to handle that, including factoring the APIs of interest 
 out of P and into a private protocol Q, then declaring the Forwardee’s 
 conformance to Q.  Now, there’s an expressivity problem with our current 
 access control system that you can’t use an internal or private protocol 
 to provide public API, but that should be fixed separately.
>>> 
>>> I'm not sure where Q comes into play in this specific example.  The idea 
>>> here is that forwarding implementations of all members of P are synthesized 
>>> by the forward declaration.  It is left up to Forwarder to decide whether 
>>> or not to declare actual conformance to P.  I am also confused by "then 
>>> declaring the Forwardee’s conformance to Q" because we are discussing 
>>> Forwarder's conformance here, not Forwardee’s.
>> 
>> Presumably both ends of the forwarding arrangement would have to conform to 
>> the same protocol, no?
> 
> No.  This is addressed in the proposal and the lazy collections motivating 
> example I replied with last night.  I don’t think it’s a good idea to require 
> this.
> 
> The forwardee needs to implement the members of the protocol but does not 
> need to conform.  The forwarder will receive forwarding implementations of 
> the members, but again does not need to declare conformance.  Forwarding is 
> orthogonal to conformance, just as it is today when you manually write 
> forwarding members today.
> 
>> 
>>> What do you have in mind when you mention using a private or internal 
>>> protocol to provide public API?  It sounds like that might be 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Matthew Johnson via swift-evolution

> On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de> wrote:
> 
> 
>> I don’t want this thread to get distracted with memberwise initialization
> Makes sense in general, but Kotlin solves those problems as a whole, and the 
> major benefit of their approach is that everything fits together really fine.
> But I'll skip everything that is not related to forwarding.
> 
>> One approach I considered would look like this:
>> 
>> class Forwarder: P {
>>// I didn’t like `implements` but didn’t have a better idea before I 
>> abandoned this approach
>>var forwardee: Forwardee implements P 
>> }
> Honestly, I'm can't see the value this discarded variant has for this 
> discussion… you have to pit your proposal against Kotlin if you really want 
> to convince anyone of its superiority.
> 
>> With the memberwise initialization proposal you also have the initializer 
>> synthesized automatically.  The only thing it doesn’t do that your Kotlin 
>> example does is automatically declare conformance.  This was an intentional 
>> design decision because it allows for additional expressivity.  This is 
>> addressed in the alternatives considered section of the proposal.  
> Can you be more precise? Kotlin clearly states what a class is doing in its 
> first line, with all expressivity that is necessary by practical means.

What I mean is this.  In the example you gave and the syntax Kotlin uses:

class Forwarder(forwardee: Forwardee): P by forwardee {}

Forwarding is coupled to protocol conformance.  This means I cannot use 
forwarding without conforming to the protocol that is forwarded.  

Here is a quick example using the syntax of my proposal to demonstrate the 
difference:

class Forwarder {
  let forwardee: Forwardee
  forward P to forwardee
}

vs

class Forwarder: P {
  let forwardee: Forwardee
  forward P to forwardee
}

In the first example Forwarder does not conform to P.  Forwarding is only used 
to synthesize the members of P.  I am greatly expanding the motivation section 
of the proposal and will have examples showing where this is what you want.  
The lazy collections section I posted last night includes the first examples 
where this is the case.

In the second example here Forwarder does conform to P.  The author of 
Forwarder has the flexibility to specify whether conformance is desired or not.

> 
>> Another difference that is maybe subtle but I think important is that with 
>> the approach I considered forwarding is declared in the body of a type or 
>> extension which emphasizes the fact that forwarding is an implementation 
>> detail, not something users of the type should be concerned with.
> But what is the benefit of this emphasis? No solution requires to make the 
> details visible in the public interface, and the ability to bury an important 
> thing like protocol conformance somewhere in the class implementation is no 
> advantage for me.

Protocol conformance is not buried in the implementation in my solution.  I 
hope the previous example makes that clear.  What is buried in the 
implementation is the forwarding declaration which causes the compiler to 
synthesize forwarding member implementations.  This synthesis is an 
implementation detail and should not be visible outside the implementation.

> 
>> This approach was abandoned as it leads to problems in expressivity and 
>> clarity.  Please see alternatives considered for an elaboration of that.  
>> This is especially true with the new approach to handling Self values that 
>> Brent suggested.  That approach requires additional syntax around the 
>> forwarding declaration, but adds both clarity and expressiveness.
> I think there is little need to worry about expressiveness for a feature that 
> most potential users will probably never utilize in real code — and I don't 
> think options like not conforming to a protocol that is forwarded is a big 
> win here. It looks to me like you are optimizing for very uncommon cases, and 
> sacrificing ease of use in the situations that are the most common by far.

Like I stated, I am working on adding several examples of how this feature can 
be used in real code.  Please have a look at the lazy collections example I 
shared last night.  This example, as well as at least one other coming examples 
take advantage of the ability to use forwarding without requiring conformance.

As with the memberwise initialization proposal, the syntax you would like to 
see can easily be added as syntactic sugar on top of the current proposal.  I 
would not support that as I do not like the syntax Kotlin uses for reasons 
already stated, but that shouldn’t stop you from pursuing a proposal for it.  
Maybe a lot of people would agree with you and it would be accepted.

Matthew

> 
>> It appears to me that you value conciseness very highly.  I do value 
>> conciseness but I also value safety, clarity, and expressiveness.  
> No, I value elegance and simplicity  — they often lead to clarity and safety.
> 
>>> 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Dave Abrahams via swift-evolution

-Dave

> On Dec 31, 2015, at 7:33 AM, Matthew Johnson via swift-evolution 
>  wrote:
> 
>> 
>> On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de > 
>> wrote:
>> 
>> 
>>> I don’t want this thread to get distracted with memberwise initialization
>> Makes sense in general, but Kotlin solves those problems as a whole, and the 
>> major benefit of their approach is that everything fits together really fine.
>> But I'll skip everything that is not related to forwarding.
>> 
>>> One approach I considered would look like this:
>>> 
>>> class Forwarder: P {
>>>// I didn’t like `implements` but didn’t have a better idea before I 
>>> abandoned this approach
>>>var forwardee: Forwardee implements P 
>>> }
>> Honestly, I'm can't see the value this discarded variant has for this 
>> discussion… you have to pit your proposal against Kotlin if you really want 
>> to convince anyone of its superiority.
>> 
>>> With the memberwise initialization proposal you also have the initializer 
>>> synthesized automatically.  The only thing it doesn’t do that your Kotlin 
>>> example does is automatically declare conformance.  This was an intentional 
>>> design decision because it allows for additional expressivity.  This is 
>>> addressed in the alternatives considered section of the proposal.  
>> Can you be more precise? Kotlin clearly states what a class is doing in its 
>> first line, with all expressivity that is necessary by practical means.
> 
> What I mean is this.  In the example you gave and the syntax Kotlin uses:
> 
> class Forwarder(forwardee: Forwardee): P by forwardee {}
> 
> Forwarding is coupled to protocol conformance.  This means I cannot use 
> forwarding without conforming to the protocol that is forwarded.  
> 
> Here is a quick example using the syntax of my proposal to demonstrate the 
> difference:
> 
> class Forwarder {
>   let forwardee: Forwardee
>   forward P to forwardee
> }
> 
> vs
> 
> class Forwarder: P {
>   let forwardee: Forwardee
>   forward P to forwardee
> }
> 
> In the first example Forwarder does not conform to P.  Forwarding is only 
> used to synthesize the members of P.  I am greatly expanding the motivation 
> section of the proposal and will have examples showing where this is what you 
> want.  The lazy collections section I posted last night includes the first 
> examples where this is the case.
> 
> In the second example here Forwarder does conform to P.  The author of 
> Forwarder has the flexibility to specify whether conformance is desired or 
> not.

There are ways to handle that, including factoring the APIs of interest out of 
P and into a private protocol Q, then declaring the Forwardee’s conformance to 
Q.  Now, there’s an expressivity problem with our current access control system 
that you can’t use an internal or private protocol to provide public API, but 
that should be fixed separately.

> 
>> 
>>> Another difference that is maybe subtle but I think important is that with 
>>> the approach I considered forwarding is declared in the body of a type or 
>>> extension which emphasizes the fact that forwarding is an implementation 
>>> detail, not something users of the type should be concerned with.
>> But what is the benefit of this emphasis? No solution requires to make the 
>> details visible in the public interface, and the ability to bury an 
>> important thing like protocol conformance somewhere in the class 
>> implementation is no advantage for me.
> 
> Protocol conformance is not buried in the implementation in my solution.  I 
> hope the previous example makes that clear.  What is buried in the 
> implementation is the forwarding declaration which causes the compiler to 
> synthesize forwarding member implementations.  This synthesis is an 
> implementation detail and should not be visible outside the implementation.
> 
>> 
>>> This approach was abandoned as it leads to problems in expressivity and 
>>> clarity.  Please see alternatives considered for an elaboration of that.  
>>> This is especially true with the new approach to handling Self values that 
>>> Brent suggested.  That approach requires additional syntax around the 
>>> forwarding declaration, but adds both clarity and expressiveness.
>> I think there is little need to worry about expressiveness for a feature 
>> that most potential users will probably never utilize in real code — and I 
>> don't think options like not conforming to a protocol that is forwarded is a 
>> big win here. It looks to me like you are optimizing for very uncommon 
>> cases, and sacrificing ease of use in the situations that are the most 
>> common by far.
> 
> Like I stated, I am working on adding several examples of how this feature 
> can be used in real code.  Please have a look at the lazy collections example 
> I shared last night.  This example, as well as at least one other coming 
> examples take advantage of the ability to use forwarding without requiring 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Dec 31, 2015, at 10:09 AM, Dave Abrahams  wrote:
> 
> 
> -Dave
> 
>>> On Dec 31, 2015, at 7:33 AM, Matthew Johnson via swift-evolution 
>>>  wrote:
>>> 
>>> 
 On Dec 31, 2015, at 5:04 AM, Tino Heth <2...@gmx.de> wrote:
 
 
 I don’t want this thread to get distracted with memberwise initialization
>>> Makes sense in general, but Kotlin solves those problems as a whole, and 
>>> the major benefit of their approach is that everything fits together really 
>>> fine.
>>> But I'll skip everything that is not related to forwarding.
>>> 
 One approach I considered would look like this:
 
 class Forwarder: P {
// I didn’t like `implements` but didn’t have a better idea before I 
 abandoned this approach
var forwardee: Forwardee implements P 
 }
>>> Honestly, I'm can't see the value this discarded variant has for this 
>>> discussion… you have to pit your proposal against Kotlin if you really want 
>>> to convince anyone of its superiority.
>>> 
 With the memberwise initialization proposal you also have the initializer 
 synthesized automatically.  The only thing it doesn’t do that your Kotlin 
 example does is automatically declare conformance.  This was an 
 intentional design decision because it allows for additional expressivity. 
  This is addressed in the alternatives considered section of the proposal. 
  
>>> Can you be more precise? Kotlin clearly states what a class is doing in its 
>>> first line, with all expressivity that is necessary by practical means.
>> 
>> What I mean is this.  In the example you gave and the syntax Kotlin uses:
>> 
>> classs Forwarder(forwardee: Forwardee): P by forwardee {}
>> 
>> Forwarding is coupled to protocol conformance.  This means I cannot use 
>> forwarding without conforming to the protocol that is forwarded.  
>> 
>> Here is a quick example using the syntax of my proposal to demonstrate the 
>> difference:
>> 
>> class Forwarder {
>>   let forwardee: Forwardee
>>   forward P to forwardee
>> }
>> 
>> vs
>> 
>> class Forwarder: P {
>>   let forwardee: Forwardee
>>   forward P to forwardee
>> }
>> 
>> In the first example Forwarder does not conform to P.  Forwarding is only 
>> used to synthesize the members of P.  I am greatly expanding the motivation 
>> section of the proposal and will have examples showing where this is what 
>> you want.  The lazy collections section I posted last night includes the 
>> first examples where this is the case.
>> 
>> In the second example here Forwarder does conform to P.  The author of 
>> Forwarder has the flexibility to specify whether conformance is desired or 
>> not.
> 
> There are ways to handle that, including factoring the APIs of interest out 
> of P and into a private protocol Q, then declaring the Forwardee’s 
> conformance to Q.  Now, there’s an expressivity problem with our current 
> access control system that you can’t use an internal or private protocol to 
> provide public API, but that should be fixed separately.

I'm not sure where Q comes into play in this specific example.  The idea here 
is that forwarding implementations of all members of P are synthesized by the 
forward declaration.  It is left up to Forwarder to decide whether or not to 
declare actual conformance to P.  I am also confused by "then declaring the 
Forwardee’s conformance to Q" because we are discussing Forwarder's conformance 
here, not Forwardee’s.

What do you have in mind when you mention using a private or internal protocol 
to provide public API?  It sounds like that might be interesting but I'm having 
trouble imagining what the syntax would look like and exactly how it would 
work.  Is this something that is planned?  What might it look like?

In any case, I don't see why that is related to requiring a Forwarder to 
conform to the forwarded protocol.  There doesn't appear to me to be a good 
reason to require that and there are reasons not to require it.  Protocols 
enable and drive the forwarding member synthesis mechanism but that mechanism 
doesn't need to require or provide conformance.  It is a third major way to use 
protocols in addition to generic constraints and existential types.

> 
>> 
>>> 
 Another difference that is maybe subtle but I think important is that with 
 the approach I considered forwarding is declared in the body of a type or 
 extension which emphasizes the fact that forwarding is an implementation 
 detail, not something users of the type should be concerned with.
>>> But what is the benefit of this emphasis? No solution requires to make the 
>>> details visible in the public interface, and the ability to bury an 
>>> important thing like protocol conformance somewhere in the class 
>>> implementation is no advantage for me.
>> 
>> Protocol conformance is not buried in the implementation in my solution.  I 
>> hope the previous example makes 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-31 Thread Dave Abrahams via swift-evolution

> On Dec 31, 2015, at 11:42 AM, Matthew Johnson  wrote:
> 
> I will continue to work on motivating examples, several of which will take 
> advantage of this relaxed requirement.

Looking forward to it!

-Dave

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-30 Thread Matthew Johnson via swift-evolution

> On Dec 29, 2015, at 5:44 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
>> On Dec 29, 2015, at 12:06 PM, Kevin Ballard via swift-evolution 
>> > wrote:
>> 
>> I briefly skimmed your proposal, so I apologize if you already addressed 
>> this, but it occurs to me that we could support automatic protocol 
>> forwarding today on a per-protocol basis simply by declaring a separate 
>> protocol that provides default implementations doing the forwarding. 
>> Handling of Self return types can then be done by adding a required 
>> initializer (or just not implementing that method, so the concrete type is 
>> forced to deal with it even though everything else is forwarded).
>>  
>> For example, if I want to automatically forward SequenceType to a member, I 
>> can do something like
>>  
>> protocol SequenceTypeForwarder : SequenceType {
>> typealias ForwardedSequenceType : SequenceType
>> 
>> var forwardedSequence : ForwardedSequenceType { get }
>> }
>> 
>> extension SequenceTypeForwarder {
>> func generate() -> ForwardedSequenceType.Generator {
>> return forwardedSequence.generate()
>> }
>> 
>> func underestimateCount() -> Int {
>> return forwardedSequence.underestimateCount()
>> }
>> 
>> func map(@noescape transform: 
>> (ForwardedSequenceType.Generator.Element) throws -> T) rethrows -> [T] {
>> return try forwardedSequence.map(transform)
>> }
>> 
>> func filter(@noescape includeElement: 
>> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
>> [ForwardedSequenceType.Generator.Element] {
>> return try forwardedSequence.filter(includeElement)
>> }
>> 
>> func forEach(@noescape body: (ForwardedSequenceType.Generator.Element) 
>> throws -> Void) rethrows {
>> return try forwardedSequence.forEach(body)
>> }
>> 
>> func dropFirst(n: Int) -> ForwardedSequenceType.SubSequence {
>> return forwardedSequence.dropFirst(n)
>> }
>> 
>> func dropLast(n: Int) -> ForwardedSequenceType.SubSequence {
>> return forwardedSequence.dropLast(n)
>> }
>> 
>> func prefix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
>> return forwardedSequence.prefix(maxLength)
>> }
>> 
>> func suffix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
>> return forwardedSequence.suffix(maxLength)
>> }
>> 
>> func split(maxSplit: Int, allowEmptySlices: Bool, @noescape isSeparator: 
>> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
>> [ForwardedSequenceType.SubSequence] {
>> return try forwardedSequence.split(maxSplit, allowEmptySlices: 
>> allowEmptySlices, isSeparator: isSeparator)
>> }
>> }
> 
> FWIW,
> 
> https://github.com/apple/swift/blob/master/stdlib/public/core/SequenceWrapper.swift
>  
> 
> 
> Though I don’t know why we still have this; it’s not used anywhere and should 
> probably be removed.  I think it was supposed to be part of the new lazy 
> sequence/collection subsystem but it was never incorporated.

Dave, thanks for pointing me to the Lazy Collections subsystem.  It made for a 
really great case study!  

A lot of what is happening in there is not directly forwarding related.  But I 
do think the implementation of the parts that involve forwarding is improved by 
using the forwarding mechanism in this proposal.  It is more clear and more 
robust than the current implementation. 

As it turns out, _SequenceWrapperType and the extension to SequenceType in 
SequenceWrapper.swift actually are still in use.  They contain an 
implementation of the forwarding mechanism Kevin Ballard suggested in this 
thread.  _CollectionWrapperType and the extension to CollectionType are not in 
use.  LazyCollection uses manual forwarding in the type itself which avoids 
some of the drawbacks of the protocol extension approach.  Of course this begs 
the question of why two different mechanisms are in use and which is actually 
preferred.

I am working on a new draft of the proposal with a greatly expanded motivation 
section.  I don’t have that completed yet, but I have completed a first pass of 
the section on the lazy collection subsystem.  I am including the current draft 
here.  I hope you find it interesting.  I am interested in your thoughts on it.

Matthew
Motivation

Delegation is a robust, composition oriented design technique that keeps 
interface and implementation inheritance separate. The primary drawback to this 
technique is that it requires a lot of manual boilerplate to forward 
implemenation to the implementing member. This proposal eliminates the need to 
write such boilerplate manually, thus making delegation-based designs much more 
convenient and attractive.

This proposal may also serve as the foundation for a future enhancement 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-30 Thread plx via swift-evolution
Thanks for writing this up.

Some quick points.

Firstly, I think it is best if the `init(_ forwardeeReturnValue: 
Forwardee)`-style initializer be replaced by something with a distinctly-named 
argument, e.g. `init(forwardeeReturnValue value: Forwardee)`. 

For use with actual wrapper types the “init(_ wrappedValue: Wrapped)`-style 
init is too valuable to “claim” for this purpose (in particular b/c we may want 
to “adjust" the forwarded result); it’s IMHO better if we use a distinct `init` 
for the forwardee-return-value scenario so we know where the value is coming 
from.

Secondly, I would prefer partial-forwarding be given more consideration, b/c it 
seems somewhat common for me in practice at this time.

EG: I would do the following somewhat frequently:

struct FooIdentifier: Equatable, Comparable, Hashable

class Foo {
  let identifier: FooIdentifier
  let name: String

  forward Hashable to identifier
}

func ==(lhs: Foo, rhs: Foo) -> Bool {
  return lhs.identifier == rhs.identifier && lhs.name == rhs.name
}

…even though I agree that full-forwarding would the most-common scenario.

I have a few other similar cases involving non-standard-library types but they 
all fit the same basic pattern as above for `Hashable`.

Finally, I’m actually at a bit of a loss for too many uses for the generic 
forwarding mechanism; if it was added I’d use it to streamline some wrapper 
types, but beyond that I’m not seeing all that many places where I’d do much 
more than that with this feature if added.

Any chance at adding a few more-concrete motivating examples for the fancier 
cases?

> On Dec 29, 2015, at 10:37 AM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> I have completed a first draft of a proposal to introduce automatic protocol 
> forwarding.  I’m looking forward to feedback from everyone!

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-30 Thread plx via swift-evolution

> On Dec 30, 2015, at 10:27 AM, Matthew Johnson  wrote:
> 
> 
>> On Dec 30, 2015, at 10:06 AM, plx via swift-evolution 
>>  wrote:
>> 
>> Thanks for writing this up.
> 
> Thanks for responding with comments.
> 
>> 
>> Some quick points.
>> 
>> Firstly, I think it is best if the `init(_ forwardeeReturnValue: 
>> Forwardee)`-style initializer be replaced by something with a 
>> distinctly-named argument, e.g. `init(forwardeeReturnValue value: 
>> Forwardee)`. 
>> 
>> For use with actual wrapper types the “init(_ wrappedValue: Wrapped)`-style 
>> init is too valuable to “claim” for this purpose (in particular b/c we may 
>> want to “adjust" the forwarded result); it’s IMHO better if we use a 
>> distinct `init` for the forwardee-return-value scenario so we know where the 
>> value is coming from.
> 
> Did you look at the approach Brent suggested yesterday?  I’m going to update 
> the proposal using something similar to that.  We won’t be claiming any init 
> at all.  It will be slightly less concise in the common case but will add 
> clarity, expressiveness, and resolve problems related to forwarding to more 
> than one member of the same type.

I did not but will make sure to read it.

> 
>> 
>> Secondly, I would prefer partial-forwarding be given more consideration, b/c 
>> it seems somewhat common for me in practice at this time.
> 
> If somebody from the core team was enthusiastic about including partial 
> forwarding in the initial proposal rather than as an enhancement that would 
> certainly motivate me to reconsider.
> 
> As I stated earlier and in the proposal, one reason I left it out is that 
> partial forwarding introduces similar concerns that arise with subclassing.  
> Should a protocol or a type designed to be a forwardee be able to include 
> annotations indicating that some members cannot be “overriden” by a 
> forwarder?  I haven’t had time to fully consider whether that is a good idea 
> or not and if it is, what it would look like, how it should work, etc.  I am 
> reluctant to introduce partial forwarding without really thinking this 
> through.
> 
>> 
>> EG: I would do the following somewhat frequently:
>> 
>> struct FooIdentifier: Equatable, Comparable, Hashable
>> 
>> class Foo {
>> let identifier: FooIdentifier
>> let name: String
>> 
>> forward Hashable to identifier
>> }
>> 
>> func ==(lhs: Foo, rhs: Foo) -> Bool {
>> return lhs.identifier == rhs.identifier && lhs.name == rhs.name
>> }
>> 
> 
> Thanks for providing an example!  It looks like you would have two different 
> instances representing the same entity, possibly one serving as an edit 
> buffer.  Is that why they might have the same identifier but different names? 
>  

This is suffering from the “short examples will necessarily feel contrived, 
long examples are too long to be polite” problem. Sometimes it’s just from 
laziness — a good composite `hashValue` can be hard to write, so why not stick 
with a known-good `hashValue` implementation? — and often makes sense in 
context (if you know that same-ID, logically-different objects will be rare 
enough to have negligible overall impact).

I totally agree though I’m getting essentially nothing from forwarding here.

Similar scenarios can show up somewhat *artificially* in the context of generic 
code. Here’s a somewhat-contrived example:

Suppose you want to write a generic function that can look an “old” array and a 
“new” array and infer an “edit sequence” that can be applied to transform the 
“old” one into the “new” one, with an added complication: some values in the 
“new” one are *revisions* of values from the old one (and thus !=, but still 
“representing the same thing”). 

This could be implemented a lot of different ways; one of them might look like 
this: 

protocol RecordIdentifierType : Equatable, Comparable, Hashable {} // 
etc
protocol IdentifiableRecordType : Equatable, Hashable {
  typealias Identifier: RecordIdentifierType
  typealias Data: Equatable // weakest guarantee we need for what we 
plan to use this for
  // deliberately-clunky names to avoid accidental collisions:  
  var recordIdentifier: Identifier { get }
  var recordData: Data { get }
}

func inferredEditOperations(
  forPreviousRecords previousRecords: [R],
  currentRecords: [R]) -> ArrayEditOperation {
  // exercise for reader
}

…wherein 99% of the time a typical concrete conformance would just return 
`self` as `recordData` and some appropriate property as `recordIdentifier`, but 
it’d still be handy to have an “adaptor" type laying around like this:

struct IdentifiableRecordAdaptor : 
IdentifiableRecordType {
  typealias Identifier = I
  typealias Data = D
  let recordIdentifier: I
  let recordData: D

  forwarding Hashable to RecordIdentifier
  

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-30 Thread Matthew Johnson via swift-evolution

> On Dec 30, 2015, at 11:33 AM, Patrick Gili  
> wrote:
> 
> Just finished reading your write-up. It sounds similar to the Forwardable 
> module supported by the Ruby standard library 
> (http://ruby-doc.org/stdlib-2.0.0/libdoc/forwardable/rdoc/Forwardable.html). 
> Is this the case?

It works somewhat differently, but it provides similar functionality.  As far 
as I can tell the only thing Forwardable does that this proposal does not do is 
support member renaming.  That is something that might make an interesting 
future enhancement to this proposal.

> 
> Cheers,
> -Patrick Gili

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-30 Thread Patrick R. Gili via swift-evolution
+1 

Sent from my iPad

> On Dec 30, 2015, at 6:56 PM, Matthew Johnson  wrote:
> 
> 
>> On Dec 30, 2015, at 11:33 AM, Patrick Gili  
>> wrote:
>> 
>> Just finished reading your write-up. It sounds similar to the Forwardable 
>> module supported by the Ruby standard library 
>> (http://ruby-doc.org/stdlib-2.0.0/libdoc/forwardable/rdoc/Forwardable.html). 
>> Is this the case?
> 
> It works somewhat differently, but it provides similar functionality.  As far 
> as I can tell the only thing Forwardable does that this proposal does not do 
> is support member renaming.  That is something that might make an interesting 
> future enhancement to this proposal.
> 
>> 
>> Cheers,
>> -Patrick Gili
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-30 Thread Tino Heth via swift-evolution
Have you looked at how this is handled in Kotlin?
Imho Jetbrains solution is quite elegant — especially as it also has a natural 
answer to another problem ("flexible memberwise initialization"; the whole init 
process is only a short chapter in the docs).
Of course, their approach is different, but I'd rather copy from the best than 
accept mediocrity because of the not invented here syndrome.

[short explanation: In Kotlin, we would have
class Forwarder(forwardee: Forwardee): P by forwardee {
…
}
forwardee would be available as a member, and because it is introduced before 
the protocol conformance, it can be used there without irritation.
Bonus: The designated initializer is defined at the same time.
]

As for the implementation:
Why not simply make this feature syntactic sugar and just auto-generate the 
forwarding methods?___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Matthew Johnson via swift-evolution

> On Dec 29, 2015, at 5:32 PM, Dave Abrahams  wrote:
> 
> 
>> On Dec 29, 2015, at 8:37 AM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> Motivation
>> 
>> Delegation is a robust, composition oriented design technique that keeps 
>> interface and implementation inheritance separate. The primary drawback to 
>> this technique is that it requires a lot of manual boilerplate to forward 
>> implemenation to the implementing member. This proposal eliminates the need 
>> to write such boilerplate manually, thus making delegation-based designs 
>> much more convenient and attractive.
>> 
>> This proposal may also serve as the foundation for a future enhancement 
>> allowing a very concise “newtype” declaration.
>> 
>> 
> 
> 
> Thanks for proposing this, Matthew!
> 
> The biggest thing missing here IMO (which has been missing from most of the 
> other proposals I’ve seen) are examples of real-world problems solved by this 
> proposal.  I have no doubt some forwarding mechanism would be a huge benefit, 
> but without clear examples, how do I know that this proposal actually 
> addresses the need?  One approach might be to show how the Lazy Collections 
> subsystem in the standard library can be rewritten more simply using this 
> mechanism.
> 
> -Dave
> 

Thanks for the feedback Dave!  I agree that the motivation section is a bit 
light and will work on filling it out with more detail, including specific 
examples of how it could be used to address specific problems.  ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Matthew Johnson via swift-evolution

> On Dec 29, 2015, at 5:45 PM, Charles Srstka  wrote:
> 
> On Dec 29, 2015, at 5:38 PM, Matthew Johnson  > wrote:
>> 
>> 
>>> On Dec 29, 2015, at 5:25 PM, Charles Srstka >> > wrote:
>>> 
>>> Strong +1 on this proposal. I use Objective-C’s forwarding mechanisms quite 
>>> often in my custom view code, in order to separate the code managing the 
>>> outer view, the layout of subviews within the view, and business logic into 
>>> separate classes, all while presenting a single, monolithic interface to 
>>> the user. The loss of this ability without writing tons of boilerplate is 
>>> one of the things about Swift that makes me sad.
>>> 
>>> The one thing I’d change is upgrading the partial forwarding synthesis to 
>>> the original proposal, as that’s a rather important feature IMO.
>>> 
>> 
>> Thanks Charles.  Do you disagree with the reasons I decided not to include 
>> partial forwarding in the initial proposal (it is discussed in alternatives 
>> considered)?
> 
> I see it in Future Enhancements, but not in Alternatives Considered (unless 
> I’m just missing it). However, my thinking is that this isn’t really that 
> hard to implement; just have the forwarding mechanism forward only methods 
> that aren’t already implemented in the class. This would be similar to the 
> way protocol extensions work, where if you implement the method you get that, 
> but if you don’t implement it, you get the protocol extension’s 
> implementation.
> 

You are right, I included it in that section.  It is definitely something I 
want to see supported eventually.  I just don’t want it to hold up the initial 
proposal.  

I also want to make sure any subtleties have been thoroughly considered and 
addressed before it goes forward.  I understand that it is in some sense 
similar in some sense to protocol methods with default implementations.  
However I think it is actually closer to inheritance (this proposal can in some 
respects be considered a limited and controlled form of multiple inheritance).  

The author of a protocol understands and intends the default implementations to 
be just that - defaults.  The author of the type that is forwarded to may have 
expectations that it receives all calls for all members of a protocol it 
implements and the implementation may not work correctly or as expected if that 
does not happen.  IMO, it is important to think about the implications of 
partial forwarding, limitations that may be necessary, etc.

Despite my caution around partial forwarding, there is one reason that it might 
make sense to support partial forwarding in the initial proposal.  
Specifically, it would be easy to get around the limitation by simply declaring 
a new protocol that contains only the members you want to forward and use that 
in your forwarding declaration.  And of course you can also write manual 
forwarding code.  So a limitation of the automatic forwarding mechanism 
wouldn’t stop you from doing partial forwarding, it would just make it more 
annoying.  It might be better to “complete” the design from the start for this 
reason.  I will definitely give this further thought.

Do you have specific use cases in mind for partial forwarding?  If so, please 
share them.

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Charles Srstka via swift-evolution
Strong +1 on this proposal. I use Objective-C’s forwarding mechanisms quite 
often in my custom view code, in order to separate the code managing the outer 
view, the layout of subviews within the view, and business logic into separate 
classes, all while presenting a single, monolithic interface to the user. The 
loss of this ability without writing tons of boilerplate is one of the things 
about Swift that makes me sad.

The one thing I’d change is upgrading the partial forwarding synthesis to the 
original proposal, as that’s a rather important feature IMO.

Charles

> On Dec 29, 2015, at 10:37 AM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> I have completed a first draft of a proposal to introduce automatic protocol 
> forwarding.  I’m looking forward to feedback from everyone!
> Automatic protocol forwarding
> 
> Proposal: SE- 
> 
> Author(s): Matthew Johnson 
> Status: Review
> Review manager: TBD
> Introduction
> 
> Automatic protocol forwarding introduces the ability to use delegation 
> without the need write forwarding member implementations manually. 
> 
> A preliminary mailing list thread on this topic had the subject protocol 
> based invocation forwarding 
> 
> Motivation
> 
> Delegation is a robust, composition oriented design technique that keeps 
> interface and implementation inheritance separate. The primary drawback to 
> this technique is that it requires a lot of manual boilerplate to forward 
> implemenation to the implementing member. This proposal eliminates the need 
> to write such boilerplate manually, thus making delegation-based designs much 
> more convenient and attractive.
> 
> This proposal may also serve as the foundation for a future enhancement 
> allowing a very concise “newtype” declaration.
> 
> Proposed solution
> 
> I propose introducing a forward declaration be allowed within a type 
> declaration or type extension. The forward declaration will cause the 
> compiler to synthesize implementations of the members required by the 
> forwarded protocols. The synthesized implementations will simply forward the 
> method call to the specified member.
> 
> The basic declaration looks like this:
> 
> forward Protocol, OtherProtocol to memberIdentifier
> The first clause contains a list of protocols to forward. 
> 
> The second clause specifies the identifier of the property to which the 
> protocol members will be forwarded. Any visible property that implements the 
> members required by the protocol is eligible for forwarding. It does not 
> matter whether it is stored, computed, lazy, etc.
> 
> It is also possible to include an access control declaration modifier to 
> specify the visibility of the synthesized members.
> 
> Self parameters
> 
> When a protocol member includes a Self parameter forwarding implementations 
> must accept the forwarding type but supply an argument of the forwardee type 
> when making the forwarding call. The most straightforward way to do this is 
> to simply use the same property getter that is used when forwarding. This is 
> the proposed solution.
> 
> Self return types
> 
> When a protocol member includes a Self return type forwarding implementations 
> must return the forwarding type. However, the forwardee implmentation will 
> return a value of the forwardee type. This result must be used to produce a 
> value of the forwarding type in some way.
> 
> The solution in this proposal is based on an ad-hoc overloading convention. A 
> protocol-based solution would probably be desirable if it were possible, 
> however it is not. This proposal supports forwarding to more than one member, 
> possibly with different types. A protocol-based solution would require the 
> forwarding type to conform to the “Self return value conversion” protocol 
> once for each forwardee type.
> 
> Static members
> 
> When a forwardee value is returned from a static member an initializer will 
> be used to produce a final return value. The initializer must be visible at 
> the source location of the forward declaration and must look like this:
> 
> struct Forwarder {
> let forwardee: Forwardee
> forward P to forwardee
> init(_ forwardeeReturnValue: Forwardee) { //... }
> }
> Instance members
> 
> When a forwardee value is returned from an instance member an instance method 
> will be used to transform the return value into a value of the correct type. 
> An instance method is necessary in order to allow the forwarding type to 
> access the state of the instance upon which the method was called when 
> performing the transformation.
> 
> If the instance method is not implemented the initializer used for static 
> members will be used instead.
> 
> The transformation has the form:
> 
> struct Forwarder 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Matthew Johnson via swift-evolution

> On Dec 29, 2015, at 6:10 PM, Brent Royal-Gordon  
> wrote:
> 
>>> * Does it have to be a protocol? Why not also allow the concrete type of 
>>> the property you're forwarding to? Obviously you couldn't form a subtype 
>>> relationship (unless you could...), but this might be useful to reduce 
>>> boilerplate when you're proxying something.
>> 
>> This is addressed in the alternatives considered section.
> 
> Sorry, I missed that, probably because the sample code in that section didn't 
> show such a forwarding.
> 
>> The short answer is that there the direct interface of the concrete type 
>> does not contain sufficient information about potential Self parameters to 
>> do this well.  This information does exist in the protocol declarations.  
>> Allowing this information to be specified in concrete interfaces would add 
>> enough complexity to the language that I don’t think it is worthwhile.
> 
> That's a good point. You could perhaps add a way to tweak the forwarding of 
> certain members, but that'd be a little tricky.

I gave this enough consideration to be leaning pretty strongly in the direction 
that protocols are the best way to do this.  

Doing this properly for the concrete interface would require an `InvariantSelf` 
type that could be used in any method signature.  It would also need to be 
actually used correctly in practice by types that were forwarded to.  The 
distinction is pretty subtle when you’re dealing with a concrete interface and 
my instinct is that people would get it wrong a lot of the time.  

Because protocols are inherently generic it is a little more straightforward to 
think about when you mean `Self` and when you mean a concrete type.

The good news is that you can declare a protocol containing the full interface 
of a concrete type if you really want or need to and use that for forwarding.  
The advantage of requiring a protocol here is that it requires you to 
consciously think about whether each parameter and return type is intended to 
be concrete or an abstract Self.  It also allows you to properly forward an 
interface even if the original author did not consider these issues when 
implementing the type.

In the following example, should the other parameter and the return type be 
`Self ` or `Double`?  It is not possible to know unless there is a protocol 
that declares foo.

extension Double {
func foo(other: Double) -> Double {
return self
}
}

> 
> One of the things I'd like to see is the ability to proxy for an instance 
> without the person writing the proxy knowing which instances it'll be used 
> with. Think, for example, of the Cocoa animator proxy, or 
> `NSUndoManager.prepareWithInvocationTarget(_:)`. It'd be nice if a Swift 
> equivalent could return, say, `NSAnimatorProxy` or 
> `NSUndoManager.InvocationTarget`, which has all the methods of the 
> generic type but records the calls for later use.
> 
> Of course, what you really want is for only a particular subset of the 
> methods to be available on the proxy (animated methods on `NSAnimatorProxy`, 
> Void methods on `NSUndoManager.InvocationTarget`), and of course in these 
> cases you're not calling directly through to the underlying methods. So I 
> might just be barking up the wrong tree here.

I can see how it might be desirable to forward to a type you receive as a 
generic parameter.  However, you would need to constrain that type to a 
protocol(s) in order to actually do anything useful with it.  That same 
protocol(s) could also be used in the forwarding declaration.

If you want is to be able to forward a set of methods that is determined by the 
generic parameter, that just isn’t going to be possible.  At least not without 
significant changes to other parts of the language providing capabilities that 
would allow you to implement something like that manually.

> 
>>> * Why the method-based conversion syntax for return values, rather than 
>>> something a little more like a property declaration?
>>> 
>>> var number: Int
>>> forward IntegerType to number {
>>> static return(newValue: Int) {
>>> return NumberWrapper(newValue)
>>> }
>>> return(newValue: Int) {
>>> return NumberWrapper(newValue)
>>> }
>>> }
>> 
>> This is actually a really good idea to consider!  I didn’t consider 
>> something like this mostly because I didn’t think of it.  I’m going to 
>> seriously consider adopting an approach along these lines.
> 
> Great.
> 
>> One possible advantage of the approach I used is that the initializer may 
>> already exist for other reasons and you would not need to do any extra work.
> 
> True. But it may also exist and *not* do what you want in the forwarding 
> case. It's easier to explicitly use the right initializer than it is to work 
> around the forwarding system implicitly using the wrong one.

Right, I am generally leaning pretty strongly 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Matthew Johnson via swift-evolution
Hi Kevin,

Thanks for taking time to look at the proposal.

The technique you show here is not bad, but it has several deficiencies IMO 
which are addressed by the solution in the proposal.

1. Forwarding should be an implementation detail, not exposed as it is with 
this method.
2. As such, the getter for the forwardee is visible.  The forwardee is an 
implementation detail that should not be visible in most cases.
3. There is no way to specify access control for the synthesized methods and if 
there were it would be coupled to the access control of the conformance.
4. You can't forward to a type that doesn't conform to the protocol.  This is 
particularly important for existential forwardees (at least until they conform 
to their protocol).
5. A type that can't conform to the protocol can't forward an implementation of 
the members of the protocol.  Specifically, non-final classes cannot 
automatically forward a group of methods to an implementer.
6. This solution does not lay the foundation for a newtype feature. It would be 
possible to have a specialized newtype feature, but why not build it on top of 
a more general forwarding feature?

You may be right that many protocols are not amenable to forwarding.  The 
motivation for this proposal is that it enables delegation-based designs to be 
implemented succinctly.  In that use case the protocols will be designed 
alongside concrete implementations and types that forward to them.  A secondary 
motivation for this proposal is to lay a foundation for a newtype feature.  In 
that case the protocols to be forwarded would be specifically designed to 
represent the portion of the interface of the wrapped type which should be 
visible to users of the newtype.

I hope these points might be enough to convince you that it is worth a closer 
look.

Matthew

> On Dec 29, 2015, at 2:06 PM, Kevin Ballard via swift-evolution 
>  wrote:
> 
> I briefly skimmed your proposal, so I apologize if you already addressed 
> this, but it occurs to me that we could support automatic protocol forwarding 
> today on a per-protocol basis simply by declaring a separate protocol that 
> provides default implementations doing the forwarding. Handling of Self 
> return types can then be done by adding a required initializer (or just not 
> implementing that method, so the concrete type is forced to deal with it even 
> though everything else is forwarded).
>  
> For example, if I want to automatically forward SequenceType to a member, I 
> can do something like
>  
> protocol SequenceTypeForwarder : SequenceType {
> typealias ForwardedSequenceType : SequenceType
> 
> var forwardedSequence : ForwardedSequenceType { get }
> }
> 
> extension SequenceTypeForwarder {
> func generate() -> ForwardedSequenceType.Generator {
> return forwardedSequence.generate()
> }
> 
> func underestimateCount() -> Int {
> return forwardedSequence.underestimateCount()
> }
> 
> func map(@noescape transform: 
> (ForwardedSequenceType.Generator.Element) throws -> T) rethrows -> [T] {
> return try forwardedSequence.map(transform)
> }
> 
> func filter(@noescape includeElement: 
> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
> [ForwardedSequenceType.Generator.Element] {
> return try forwardedSequence.filter(includeElement)
> }
> 
> func forEach(@noescape body: (ForwardedSequenceType.Generator.Element) 
> throws -> Void) rethrows {
> return try forwardedSequence.forEach(body)
> }
> 
> func dropFirst(n: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.dropFirst(n)
> }
> 
> func dropLast(n: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.dropLast(n)
> }
> 
> func prefix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.prefix(maxLength)
> }
> 
> func suffix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.suffix(maxLength)
> }
> 
> func split(maxSplit: Int, allowEmptySlices: Bool, @noescape isSeparator: 
> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
> [ForwardedSequenceType.SubSequence] {
> return try forwardedSequence.split(maxSplit, allowEmptySlices: 
> allowEmptySlices, isSeparator: isSeparator)
> }
> }
>  
> With this protocol declared, I can then say something like
>  
> struct Foo {
> var ary: [Int]
> }
> 
> extension Foo : SequenceTypeForwarder {
> var forwardedSequence: [Int] { return ary }
> }
>  
> and my struct Foo now automatically implements SequenceType by forwarding to 
> its variable `ary`.
>  
> The downside to this is it needs to be manually declared for each protocol. 
> But I wager that most protocols actually aren't really amenable to forwarding 
> anyway.
>  
> -Kevin Ballard
> 
> ___
> 

Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Matthew Johnson via swift-evolution

> On Dec 29, 2015, at 3:08 PM, Brent Royal-Gordon  
> wrote:
> 
>> I have completed a first draft of a proposal to introduce automatic protocol 
>> forwarding.  I’m looking forward to feedback from everyone!
> 
> Some things I don't see discussed here:
> 
> * Does it have to be a protocol? Why not also allow the concrete type of the 
> property you're forwarding to? Obviously you couldn't form a subtype 
> relationship (unless you could...), but this might be useful to reduce 
> boilerplate when you're proxying something.

This is addressed in the alternatives considered section.  The short answer is 
that there the direct interface of the concrete type does not contain 
sufficient information about potential Self parameters to do this well.  This 
information does exist in the protocol declarations.  Allowing this information 
to be specified in concrete interfaces would add enough complexity to the 
language that I don’t think it is worthwhile.  Joe Groff and I discussed this 
briefly yesterday: 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151228/004660.html
 
.

What you *can* do is declare a protocol containing the generalized signatures 
(substituting Self where appropriate) of all of the members of your concrete 
interface that you wish to be available to forward.  That is a one-time 
protocol declaration that allows you to forward the concrete interface as many 
times as you wish.  It seems like a reasonable tradeoff.

> 
> * Why the method-based conversion syntax for return values, rather than 
> something a little more like a property declaration?
> 
>   var number: Int
>   forward IntegerType to number {
>   static return(newValue: Int) {
>   return NumberWrapper(newValue)
>   }
>   return(newValue: Int) {
>   return NumberWrapper(newValue)
>   }
>   }

This is actually a really good idea to consider!  I didn’t consider something 
like this mostly because I didn’t think of it.  I’m going to seriously consider 
adopting an approach along these lines.

One possible advantage of the approach I used is that the initializer may 
already exist for other reasons and you would not need to do any extra work.

A big advantage of this approach is that it would work even when you are 
forwarding different protocols to more than one member with the same type.

> 
> * If you want to keep the method-based syntax, why use the `init(_:)` 
> initializer instead of one specifically for forwarding, like 
> `init(forwardedReturnValue:)`?

That was a somewhat arbitrary decision I suppose.  I also considered having the 
compiler look for any initializer accepting the correct type regardless of 
label.

> 
> * If you want to keep the method-based syntax, why do all forwards, even to 
> different members, share the same transformation method? Wouldn't it be 
> better to have, for instance, `init(returnedNumber:)` and 
> `transformedReturnedNumber(_:)`, so that forwards to other properties could 
> use different logic?

That is a limitation of the approach I used and the proposal disallows you to 
do such forwarding because of the ambiguity.  I am glad you identified a 
solution to that!

> 
> * If you want to keep the method-based syntax, would it make sense to instead 
> have an initializer for instance initializers too, and just have it take a 
> second parameter with the instance?
> 
>   init(forwardedReturnValue: Int) {...}
>   init(forwardedReturnValue: Int, from: NumberWrapper) {…}

Part of the reason the instance method was used is because sometimes the right 
thing to do might be to mutate and then return self.  Using an instance method 
gives you the flexibility to do that if necessary.

> 
> * Does this mean that a `public forward` declaration would forward `internal` 
> members through synthesized `public` interfaces, if the forwarder and 
> forwardee happened to be in the same module?
> 
>> All synthesized members recieve access control modifiers matching the access 
>> control modifier applied to the forward declaration.

Yes, if the forwardee had internal visibility and the forwarder was public the 
forwarder could publicly forward the interface.  This is intentional behavior.  
The forwardee may well be an internal implementation detail while the methods 
of the protocol are part of the public interface of the forwarder.  It is 
possible to write code that does this manually today.

> * You don't explicitly mention this, but I assume mutating methods work and 
> mutate `self`?

Mutating methods are something I didn’t think about carefully yet.  Thanks for 
pointing that out!  But generally, yes a forwarding implementation of a 
mutating method would need to mutate the forwardee which is part of self, thus 
mutating self.

> 
> -- 
> Brent Royal-Gordon
> Architechies
> 


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Kevin Ballard via swift-evolution
On Tue, Dec 29, 2015, at 02:11 PM, Joe Groff wrote:
>
>> On Dec 29, 2015, at 1:24 PM, Matthew Johnson via swift-evolution > evolut...@swift.org> wrote:
>>
>> Hi Kevin,
>>
>> Thanks for taking time to look at the proposal.
>>
>> The technique you show here is not bad, but it has several
>> deficiencies IMO which are addressed by the solution in the proposal.
>>
>> 1. Forwarding should be an implementation detail, not exposed as it
>>is with this method.
>
> This could theoretically be managed by access control on protocol
> conformances:
>
>> public struct Foo: internal SequenceTypeForwarder, public
>> SequenceType { ... }
>
> though that's even more boilerplatey, and makes it easy to
> accidentally expose more API than you intended to.

That's an interesting approach.

Another workaround for this today is to use an operator (similar to how
the stdlib uses ~> internally for a lot of stuff) coupled with a phantom
type. As an example (using ~> because why not):

// phantom type

struct _SequenceTypeForwarder {}




protocol SequenceTypeForwarder : SequenceType {

typealias ForwardedSequenceType : SequenceType




func ~>(this: Self, _: _SequenceTypeForwarder) -> ForwardedSequenceType

}


The need for the phantom type is a bit unfortunate (you can't just use
SequenceTypeForwarder.Protocol because it complains about the Self or
associated type requirements issue).

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Kevin Ballard via swift-evolution
I briefly skimmed your proposal, so I apologize if you already addressed
this, but it occurs to me that we could support automatic protocol
forwarding today on a per-protocol basis simply by declaring a separate
protocol that provides default implementations doing the forwarding.
Handling of Self return types can then be done by adding a required
initializer (or just not implementing that method, so the concrete type
is forced to deal with it even though everything else is forwarded).

For example, if I want to automatically forward SequenceType to a
member, I can do something like

protocol SequenceTypeForwarder : SequenceType {

typealias ForwardedSequenceType : SequenceType




var forwardedSequence : ForwardedSequenceType { get }

}




extension SequenceTypeForwarder {

func generate() -> ForwardedSequenceType.Generator {

return forwardedSequence.generate()

}




func underestimateCount() -> Int {

return forwardedSequence.underestimateCount()

}




func map(@noescape transform:
(ForwardedSequenceType.Generator.Element) throws -> T) rethrows -> [T] {

return try forwardedSequence.map(transform)

}




func filter(@noescape includeElement:
(ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows ->
[ForwardedSequenceType.Generator.Element] {

return try forwardedSequence.filter(includeElement)

}




func forEach(@noescape body: (ForwardedSequenceType.Generator.Element)
throws -> Void) rethrows {

return try forwardedSequence.forEach(body)

}




func dropFirst(n: Int) -> ForwardedSequenceType.SubSequence {

return forwardedSequence.dropFirst(n)

}




func dropLast(n: Int) -> ForwardedSequenceType.SubSequence {

return forwardedSequence.dropLast(n)

}




func prefix(maxLength: Int) -> ForwardedSequenceType.SubSequence {

return forwardedSequence.prefix(maxLength)

}




func suffix(maxLength: Int) -> ForwardedSequenceType.SubSequence {

return forwardedSequence.suffix(maxLength)

}




func split(maxSplit: Int, allowEmptySlices: Bool, @noescape isSeparator:
(ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows ->
[ForwardedSequenceType.SubSequence] {

return try forwardedSequence.split(maxSplit, allowEmptySlices:
allowEmptySlices, isSeparator: isSeparator)

}

}


With this protocol declared, I can then say something like

struct Foo {

var ary: [Int]

}




extension Foo : SequenceTypeForwarder {

var forwardedSequence: [Int] { return ary }

}


and my struct Foo now automatically implements SequenceType by
forwarding to its variable `ary`.

The downside to this is it needs to be manually declared for each
protocol. But I wager that most protocols actually aren't really
amenable to forwarding anyway.

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Brent Royal-Gordon via swift-evolution
> I have completed a first draft of a proposal to introduce automatic protocol 
> forwarding.  I’m looking forward to feedback from everyone!

Some things I don't see discussed here:

* Does it have to be a protocol? Why not also allow the concrete type of the 
property you're forwarding to? Obviously you couldn't form a subtype 
relationship (unless you could...), but this might be useful to reduce 
boilerplate when you're proxying something.

* Why the method-based conversion syntax for return values, rather than 
something a little more like a property declaration?

var number: Int
forward IntegerType to number {
static return(newValue: Int) {
return NumberWrapper(newValue)
}
return(newValue: Int) {
return NumberWrapper(newValue)
}
}

* If you want to keep the method-based syntax, why use the `init(_:)` 
initializer instead of one specifically for forwarding, like 
`init(forwardedReturnValue:)`?

* If you want to keep the method-based syntax, why do all forwards, even to 
different members, share the same transformation method? Wouldn't it be better 
to have, for instance, `init(returnedNumber:)` and 
`transformedReturnedNumber(_:)`, so that forwards to other properties could use 
different logic?

* If you want to keep the method-based syntax, would it make sense to instead 
have an initializer for instance initializers too, and just have it take a 
second parameter with the instance?

init(forwardedReturnValue: Int) {...}
init(forwardedReturnValue: Int, from: NumberWrapper) {...}

* Does this mean that a `public forward` declaration would forward `internal` 
members through synthesized `public` interfaces, if the forwarder and forwardee 
happened to be in the same module?

> All synthesized members recieve access control modifiers matching the access 
> control modifier applied to the forward declaration.


* You don't explicitly mention this, but I assume mutating methods work and 
mutate `self`?

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Félix Cloutier via swift-evolution
As the resident you-can-already-do-this grumpy guy, I tend to agree that most 
protocols aren't easily amenable to forwarding, and this solution works too.

In general, I think that Swift already doesn't impose too much boilerplate, and 
I think that most features to reduce boilerplate would be better served by 
having a sane macro system in Swift. (This is probably not in scope for Swift 
3, though.)

Félix

> Le 29 déc. 2015 à 15:06:48, Kevin Ballard via swift-evolution 
>  a écrit :
> 
> I briefly skimmed your proposal, so I apologize if you already addressed 
> this, but it occurs to me that we could support automatic protocol forwarding 
> today on a per-protocol basis simply by declaring a separate protocol that 
> provides default implementations doing the forwarding. Handling of Self 
> return types can then be done by adding a required initializer (or just not 
> implementing that method, so the concrete type is forced to deal with it even 
> though everything else is forwarded).
>  
> For example, if I want to automatically forward SequenceType to a member, I 
> can do something like
>  
> protocol SequenceTypeForwarder : SequenceType {
> typealias ForwardedSequenceType : SequenceType
> 
> var forwardedSequence : ForwardedSequenceType { get }
> }
> 
> extension SequenceTypeForwarder {
> func generate() -> ForwardedSequenceType.Generator {
> return forwardedSequence.generate()
> }
> 
> func underestimateCount() -> Int {
> return forwardedSequence.underestimateCount()
> }
> 
> func map(@noescape transform: 
> (ForwardedSequenceType.Generator.Element) throws -> T) rethrows -> [T] {
> return try forwardedSequence.map(transform)
> }
> 
> func filter(@noescape includeElement: 
> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
> [ForwardedSequenceType.Generator.Element] {
> return try forwardedSequence.filter(includeElement)
> }
> 
> func forEach(@noescape body: (ForwardedSequenceType.Generator.Element) 
> throws -> Void) rethrows {
> return try forwardedSequence.forEach(body)
> }
> 
> func dropFirst(n: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.dropFirst(n)
> }
> 
> func dropLast(n: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.dropLast(n)
> }
> 
> func prefix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.prefix(maxLength)
> }
> 
> func suffix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
> return forwardedSequence.suffix(maxLength)
> }
> 
> func split(maxSplit: Int, allowEmptySlices: Bool, @noescape isSeparator: 
> (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> 
> [ForwardedSequenceType.SubSequence] {
> return try forwardedSequence.split(maxSplit, allowEmptySlices: 
> allowEmptySlices, isSeparator: isSeparator)
> }
> }
>  
> With this protocol declared, I can then say something like
>  
> struct Foo {
> var ary: [Int]
> }
> 
> extension Foo : SequenceTypeForwarder {
> var forwardedSequence: [Int] { return ary }
> }
>  
> and my struct Foo now automatically implements SequenceType by forwarding to 
> its variable `ary`.
>  
> The downside to this is it needs to be manually declared for each protocol. 
> But I wager that most protocols actually aren't really amenable to forwarding 
> anyway.
>  
> -Kevin Ballard
> 
> ___
> 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] [Proposal Draft] automatic protocol forwarding

2015-12-29 Thread Thorsten Seitz via swift-evolution
 ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution