<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 29, 2015, at 6:10 PM, Brent Royal-Gordon <<a href="mailto:brent@architechies.com" class="">brent@architechies.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" class=""><blockquote type="cite" class="">* 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.<br class=""></blockquote><br class="">This is addressed in the alternatives considered section.<br class=""></blockquote><br class="">Sorry, I missed that, probably because the sample code in that section didn't show such a forwarding.</div></div></blockquote><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class="">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.<br class=""></blockquote><br class="">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.<br class=""></div></div></blockquote><div><br class=""></div><div>I gave this enough consideration to be leaning pretty strongly in the direction that protocols are the best way to do this. </div><div><br class=""></div><div>Doing this properly for the concrete interface would require an `<span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">InvariantSelf` type that could be used in any method signature. It would also need to be actually used correctly </span><i style="white-space: pre-wrap;" class="">in practice</i><span style="white-space: pre-wrap;" class=""> 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. </span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">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.</span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">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.</span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">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.</span></span></div><div><span style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></span></div><div><span style="background-color: rgb(255, 255, 255); white-space: pre-wrap;" class="">extension Double </span><span style="white-space: pre-wrap; background-color: rgb(255, 255, 255);" class="">{</span></div><div><span style="background-color: rgb(255, 255, 255); white-space: pre-wrap;" class=""> func foo(other: Double) -> Double </span><span style="white-space: pre-wrap; background-color: rgb(255, 255, 255);" class="">{</span></div><div><span style="background-color: rgb(255, 255, 255); white-space: pre-wrap;" class=""> return self<div class=""> }</div><div class="">}</div></span></div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">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<View>` or `NSUndoManager.InvocationTarget<Target>`, which has all the methods of the generic type but records the calls for later use.</div></div></blockquote><blockquote type="cite" class=""><div class=""><div class=""><br class="">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.<br class=""></div></div></blockquote><div><br class=""></div><div>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.</div><div><br class=""></div><div>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.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">* Why the method-based conversion syntax for return values, rather than something a little more like a property declaration?<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>var number: Int<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>forward IntegerType to number {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>static return(newValue: Int) {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>return NumberWrapper(newValue)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>return(newValue: Int) {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>return NumberWrapper(newValue)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""></blockquote><br class="">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.<br class=""></blockquote><br class="">Great.<br class=""><br class=""><blockquote type="cite" class="">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.<br class=""></blockquote><br class="">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.<br class=""></div></div></blockquote><div><br class=""></div><div>Right, I am generally leaning pretty strongly towards changing the proposal to use a solution similar to what you suggest.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class="">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.<br class=""></blockquote><br class="">But again, if that's the wrong behavior, there's no good way to fix it.<br class=""></div></div></blockquote><div><br class=""></div><div>I was actually indicating an advantage of the approach you suggested <b class="">because</b> it provides a solution to that problem. :)</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">* 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?<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>init(forwardedReturnValue: Int) {...}<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>init(forwardedReturnValue: Int, from: NumberWrapper) {…}<br class=""></blockquote><br class="">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.<br class=""></blockquote><br class="">In practice, I'm not sure that's actually the case very often. How frequently will the internal type return a changed value, but your identically-named cover method ought to mutate the property? That completely changes the semantics of the underlying call.<br class=""></div></div></blockquote><div><br class=""></div><div>I would guess you are right about this being something that is never or almost never the right thing to do. Maybe a solution that actually prevents you from doing this would be a better one for that reason. </div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">I mean, what you're proposing would be something like this:<br class=""><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>class ListOfThings {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>private var actualList: [Thing]<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>func filter(predicate: Thing -> Bool) -> ListOfThings {<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>let returnValue = actualList.filter(predicate)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>actualList = returnValue<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>return ListOfThings(returnValue)<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}<br class=""><br class="">Is that a thing you actually expect people to do?<br class=""></div></div></blockquote><div><br class=""></div><div>I hope not! :) I hadn’t looked too hard for an example where it would be the right thing to do and I think you are right that such an example would be pretty hard to come by. Thanks for pushing back on this one! :)</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">* 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?<br class=""><br class=""><blockquote type="cite" class="">All synthesized members recieve access control modifiers matching the access control modifier applied to the forward declaration.<br class=""></blockquote></blockquote><br class="">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.<br class=""></blockquote><br class="">I suppose that, if it's always a protocol you're forwarding to, you can assume that none of the protocol methods are internal-only implementation details. But I have to admit that I'm still concerned about this; it just seems like a recipe for accidentally exposing things you meant to keep private.<br class=""></div></div></blockquote><div><br class=""></div><div>Think of a state or strategy pattern. You might have an internal protocol with several implementations representing the various states or strategies. You forward to a private member that is an existential of the protocol type. The synthesized forwarding methods represent the public interface. However, the protocol itself is not public as it is an implementation detail and the forwarder doesn’t even conform to the protocol. The protocol is strictly used as an implementation detail of the public interface of your type.</div><div><br class=""></div><div>I honestly don’t understand the concern about this proposal accidentally exposing things you meant to keep private. You have full control over access control of everything, including the synthesized methods. The proposal doesn’t do anything you couldn’t already do manually and it makes it very easy to keep them private if desired. If somebody wanted to manually write a forwarder that declares forwarding methods public while forwarding to internal methods on the forwardee they can do that already today! </div><div><br class=""></div><div>IMO the language needs to provide the tools to specify your intent clearly and easily and offer sensible defaults, but it can’t do more than that. I believe this proposal falls in line with that principle and also inline with how access control already works in the language today (the default for synthesized members matches the default for manual member declarations).</div><div><br class=""></div><div>I am very concerned about not exposing details that shouldn’t be exposed and that is one of the big drawbacks of the approach to protocol forwarding that Kevin Ballard shared.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">* You don't explicitly mention this, but I assume mutating methods work and mutate `self`?<br class=""></blockquote><br class="">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.<br class=""></blockquote><br class="">Well, as long as they're thought about at some point!<br class=""></div></div></blockquote><div><br class=""></div><div>Yes, I’m glad you brought them up!</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">-- <br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class=""></div></div></blockquote></div><br class=""></body></html>