> On Dec 29, 2015, at 3:08 PM, Brent Royal-Gordon <br...@architechies.com> 
> 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
 
<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
> 

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

Reply via email to