<div style="white-space:pre-wrap">I think we agree on a lot of premises but come to opposite conclusions. I would not phrase it precisely how you did, that protocol designers are currently required 'to foresee all uses.' Rather, I see an analogy with these scenarios:<br><br>a) Many functions in the standard library have preconditions for their arguments. When those preconditions are violated, execution is halted. The designer of the function writes a precondition to indicate the inputs for which he or she believes the method produces a meaningful result. If the preconditions are set too restrictively, then the caller of that function will be frustrated to find crashing code.<br><br>But is this a feature or a bug? Well, it is a bug that the designer set inappropriate preconditions. But the bug is in deficient *reasoning* by the designer; the precondition accurately reflects a failure of the designer to reason about a sensible use of the function. However, given that there has been a defect in reasoning by the designer, is it a bug or a feature that Swift refuses to execute code that hasn't been reasoned through? It is a feature.<br><br>b) Classes now cannot be subclassed outside their modules by default. This decision has been controversial, but it follows the same reasoning. The designer of the function, if he or she has reasoned through the effects of subclassing, can indicate that by making the class open. It may be the case that a designer has not put in the thought work necessary and a class is unnecessarily sealed. This would no doubt be frustrating.<br><br>Is that a bug or a feature? Again, it is a bug on the part of the designer, for not having done the necessary thought work. But is it a bug or a feature for Swift to refuse to compile code that hasn't been reasoned through? I think it has been made clear that, as an opinionated language, Swift makes the argument that this is a deliberate feature.<br><br>I argue the same thing applies here. Currently, protocols constrain the API of conforming types. If a designer has reasoned through their design correctly, then all is well. If a designer has made bad design choices, then conforming types are constrained to have bad API design. Is that a bug or a feature? It is of course a bug on the part of the designer for having designed a bad protocol. But I think it is arguably a feature on the part of Swift for refusing to allow code to circumvent the protocol's design, because a protocol that is out of the end user's control is also likely a protocol for which the default implementations are opaque to that user and can't be reasoned through by that user.<br><br>I'm not entirely sure on my position, though. To be convinced otherwise, I'd need to see a compelling real-world use case that demonstrates all of the following:<br><br>- Safety: perhaps, with protocols, unlike class inheritance, it is almost always safe to make these kinds of changes unanticipated by the original author--it would be good to see evidence either way<br><br>- Necessity: earlier, examples were cited where at least one of two conflicting protocols were under the user's control; in that case, this feature isn't needed, because that protocol's requirements can be trivially renamed<br><br>- Good design: show me that the design patterns enabled by the feature are better than what is possible with workarounds; if a renaming or hiding feature is expedient, but an alternative approach would promote less fragile or more Swifty design, then we should be exploring ways to simplify or promote an alternative approach; one consideration, for example, is that naming of anything is hard, and the current fact that protocols *need* to have well-chosen member names encourages designers to think hard--but if renaming becomes possible, could we simply be enabling less thoughtful protocol design with little benefit (to evaluate this, we would need some sense of the answer to the necessity question above)?<br></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Sep 2, 2016 at 10:56 Thorsten Seitz <<a href="mailto:tseitz42@icloud.com" target="_blank">tseitz42@icloud.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div></div><div><br></div><div><br>Am 24.08.2016 um 21:35 schrieb Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>>:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Aug 24, 2016 at 1:59 PM, Jonathan Hull <span dir="ltr"><<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Aug 24, 2016, at 7:48 AM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><br><div><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">On Wed, Aug 24, 2016 at 3:39 AM, Jonathan Hull<span> </span><span dir="ltr"><<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>></span><span> </span>wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Aug 23, 2016, at 8:35 AM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><br><div><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">On Tue, Aug 23, 2016 at 3:02 AM, Jonathan Hull<span> </span><span dir="ltr"><<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>></span><span> </span>wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Aug 22, 2016, at 11:32 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><br><div><div dir="ltr">On Mon, Aug 22, 2016 at 11:59 PM, Jonathan Hull via swift-evolution<span> </span><span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span><span> </span>wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi everyone,<br><br>We talked about this before when we were discussing mixins, and there seemed to be generally positive feelings towards it as a feature for the future.</blockquote><div><br></div><div>It's been some time now since the original discussion, so perhaps you could refresh our collective memory (or at least, mine): although it *seems* like this feature might be useful, I can't recall a concrete use case where I've felt like I needed this feature--do you have some examples?</div></div></div></div></div></blockquote><div><br></div></span><div>Ideally, the biggest use is that it helps to (partially) solve the diamond problem (and similar issues) by forcing/allowing disambiguation when there are multiple protocols being conformed to. This will become more of an issue if we allow protocols or extensions to add storage. Your proposed syntax actually does a better job of it than mine because mine was always shown as attached to some sort of implementation, whereas yours could potentially allow access to a default implementation under a new name.</div><div><br></div><div>Other than that, it generally allows us to bypass/mitigate conflicts between protocols. In the current version, you are unable to conform to both protocols (either because it won’t compile or because you can’t satisfy the semantics of both protocols) without designing the protocols together to avoid conflicts. (I have definitely had to go back and rename/refactor properties on a protocol for this reason… which I couldn’t have done if I didn’t control both protocols).</div></div></div></blockquote><div><br></div><div>I understand something of the difficulty of confronting the diamond problem. As I wrote above, I'm inclined to believe that this proposed feature would help solve a real issue. However, the point I'm trying to make is that, on reflection, I have never actually been hampered by the lack of this feature, and so I'd like to continue the discussion to get a fuller sense of just how impactful this proposal would be, both positive and negative.</div><div><br></div><div>It's true, of course, that if you control at least one of two protocols (you don't need to control both protocols), it is trivially easy to cause this problem to occur, but as you point out it is also possible to resolve the problem by re-designing the protocol you control. I'm inclined to think (without evidence, admittedly) that re-designing to remove the conflict, where possible, would actually be the superior option in most cases.</div><div><br></div><div>My question was: have you actually run into a scenario that necessitates the feature you propose because you controlled neither conflicting protocol? I think it would strengthen the proposal greatly to have a concrete, uncontrived example.</div></div></div></div></div></blockquote><div><br></div></span><div>Right now I commonly have to hand-namespace protocol methods/properties to avoid conflicts. So instead of having ‘var image:UIImage’ (which is the name which makes the most sense in the protocol’s context), I have ‘var protocolNameImage:UIImage’. There are lots of things which have common properties like ‘count’ which have to be called ‘somethingCount’ or ‘countOfSomething’. In the context of the protocol, these names are full of redundant words (especially when measured against the new naming guidelines). We are all used to doing this for Objective C, but it feels out of place in Swift.</div><div><br></div><div>This will become a much more serious issue as the third-party code ecosystem grows. Without some capability like this, you will have frameworks which can’t be used together (or at least with the same object). I would hate to see a ‘best practice’ emerge of adding 3 letter prefixes to all protocol methods to get around compatibility issues.</div></div></div></blockquote><div><br></div><div>Ah, well this isn't exactly the diamond problem you're talking about here. Instead, I think, we have a fundamental disagreement. I think I've been told that this opinion of mine is 'insane'--but I hold to it:</div></div></div></div></div></blockquote><div><br></div></span><div>Well you asked for an additional example besides the diamond problem… so no it isn’t. I did include a diamond problem example further down though…</div></div></div></blockquote><div> </div><div>Sorry, I wasn't asking for an example _besides_ the diamond problem. I was asking for more information about a concrete scenario, diamond problem or not, where an existing technique could not resolve the conflict (for instance, a scenario when you controlled neither of two conflicting protocols, and where no satisfactory alternative design existed that could avoid conforming a single type to both protocols).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span><div><br></div><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>Protocols are not merely a vehicle for delivering a reusable bag of code. One of its most essential purposes is to constrain the shape or API of its conforming types. Therefore, it is a feature, not a bug, that with every choice of name in a protocol you foreclose the possibility of composing that protocol with others that might have colliding names.</div><div><br></div><div>Currently, if you the protocol vendor have made the decision that `image` "makes the most sense in the protocol's context", you must have considered whether it would be absurd for a conforming type to have another use for `image`. If it would be absurd, then `image` </div></div></div></div></blockquote></span></div></div></blockquote></div></div></div></div></blockquote><div><br></div></div><div dir="auto">I find it a little bit strange to require from a protocol designer to foresee all future uses of a protocol. IMO protocols are not bags of code but encapsulate a certain (typically fine grained) semantic. How this semantic will be coupled with other semantics (i.e. protocols) is widely open.<div><br></div><div></div></div><div dir="auto"><div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><span><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>is the appropriate name for your protocol requirement and any other word would truly be redundant. But, if this is only one of many plausible images, then `somethingImage` or `imageOfSomething` *is* the appropriate name, and trying to shorten the name isn't at all consistent with Swift guidelines but rather an incorrect attempt to prioritize brevity over clarity.</div></div></div></div></blockquote><div><br></div></span><div>Most things that conform would have ‘image’, and it would have exactly the same semantics as my protocol. Thus their ‘image’ would provide conformance without additional work. But I have to worry about name collisions, so now I have to defensively call it ‘imageOfSomething', which they now have to implement to call their ‘image’ method.</div><span><div><br></div><br><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>What you're arguing is that protocol designers should be able to design protocols without regard for how they will compose with others in conforming types, relying on a new member-renaming feature instead. But, as you point out, you can already use a protocol as a mere bag of code by naming all members with unique, prefixed names, then have conforming types forward their own choice of names to these.</div></div></div></div></blockquote><div><br></div></span></div></div></blockquote></div></div></div></div></blockquote><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>No, I am arguing that protocol authors should design protocols in the way which makes the behavior/semantics of the protocol the most obvious to the caller. 95% of the time there won’t be collisions, but occasionally there will be and we have to have a plan for that.</div><span><div><br></div><br><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>This member-renaming feature you propose would enhance the aesthetic pleasure of the protocol designer, allowing simple names that don't ever have to appear in the public API of a concrete type to be used for a protocol member without placing any restrictions on the API of conforming types. However, I don't see anything wrong with the current hand-prefixing method being enshrined as "best practice" for the bag-of-code approach to protocols. If, as you predict, a growing third-party code ecosystem makes name collisions worse, then in fact having uniquely distinguishable prefixed members would be less confusing than having conforming types renaming protocol members as a matter of course.</div></div></div></div></blockquote><div><br></div></span><div>You are arguing that namespace collisions are a feature instead of a bug? Did you feel that way about ObjectiveC’s lack of name spacing?</div></div></div></blockquote><div><br></div><div>My argument is about protocols specifically: I understand that a major feature of protocols is that they make guarantees regarding the API of conforming types. In rare cases, two guarantees may conflict, but I do not consider that conflict to be a bug per se, as it is the inevitable result of what it means to have guarantees, i.e. it is part and parcel of the feature. In order to provide a way of resolving conflicting requirements in protocols, your solution eliminates the API-guaranteeing feature of protocols altogether.</div><div><br></div><div>I can't comment about Objective-C, because I've never written a single line of it.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>I don’t think it is anywhere near as confusing as you suggest. As I mentioned before, if you cast it to the protocol, then the original names will still work.</div></div></div></blockquote><div><br></div><div>Except when you can't cast to a protocol existential, as is the case with any protocol with Self or associated type requirements.</div></div></div></div></div></blockquote><div><br></div></div></div><div dir="auto"><div>This is a separate problem which will be solved once we have existential types.</div><div>Furhermore the argument still holds when the protocol is being used as type constrained.</div><div><br></div><div></div></div><div dir="auto"><div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>If you are trying to type the original name on the typed conformer, then showing the renamed version (with an indication of the renaming) in autocomplete should teach the change and clear up any confusion.</div></div></div></blockquote><div><br></div><div>Mine isn't an argument about usability or learnability. It's a philosophical/design point: what are protocols for? My answer: among other uses, for constraining the API of conforming types. Perhaps this view is incompatible with the view that protocols should support additional mixin-like features.</div></div></div></div></div></blockquote><div><br></div></div></div><div dir="auto"><div>I don't think this has anything to do with mixins. It is just the general problem of being able to combine protocols which have been designed independently from each other.</div><div><br></div><div></div></div><div dir="auto"><div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><span><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>To take your example of walk(). Perhaps we have a protocol ‘Walkable’ which refers to any data structure where the nodes can be walked using the ‘walk()’ function. It is easy to imagine two different protocols A & B which specialize on this in different ways (say LinearWalkable & RandomWalkable), and both add some methods/properties and use those to provide efficient default implementations. At some point, you may run into a data structure which could easily be walked in both ways.</div><div><br></div><div>As things are right now, you couldn’t inherit from both protocols. While you could add new ‘linearWalk()’ & ‘randomWalk()’ to the protocols respectively (cluttering their interface), there is still the issue of what to do when 'walk()’ is called. You can’t rename walk() in the originating protocols because it comes from their common ancestor. Much better to force one (or both) of the methods to be renamed on the conforming data structure. That keeps the interfaces of the protocols clean and makes the options available on the data structure clearer (e.g. ‘walk()’ & ‘randomWalk()’ )</div><div><br></div><div>What I have had to do in the current version is inherit from the original protocol and then copy and paste the default implementations from the specialized versions. Now my code has been duplicated and is harder to maintain. We can do better.</div><span><br></span></div></div></blockquote><div><br></div><div>I think Charles's solution is pretty nice, but he's right that the API surface area will have to grow. I don't know his original use case, so I don't know how ugly I'd find the final solution to be in that scenario. In this particular example, I'd say that having `linearWalk()` and `randomWalk()` distinguished seems pretty sensible and an overall win for clarity. If the same vendor controlled all three protocols, then `Walkable` could have the `walk()` requirement removed altogether for even more clarity.</div></div></div></div></blockquote><div><br></div></span><div>So you would remove 'walk()' from Walkable to avoid the name collision in this one case, when ‘walk()’ is Walkable’s entire reason for being?</div></div></blockquote><div><br></div><div>No, `walk()` is not Walkable's entire reason for being. Protocols guarantee semantics also. A `Walkable` protocol without any required members would still have a reason for being: conforming types are walkable.</div><div><br></div><div>On the other hand, given that Walkable certainly would have associated type requriements, if you considered that `walk()` _was_ Walkable's entire reason for being *and* you could rename `walk()` in any conforming type, how is that different from not having a `walk()` requirement at all?</div></div></div></div></div></blockquote><div><br></div></div></div><div dir="auto"><div>Generic methods using a type constrained by Walkable can call `walk()` on it. The same will be possible for variables declared with existential types in the future and it already applies for protocols without associated type or Self requirements.</div></div><div dir="auto"><div><br></div><div>-Thorsten </div><div><br></div></div><div dir="auto"><div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word"><div><div>Also, you would lose polymorphism.</div><span><div><br></div><div><br></div><br><blockquote type="cite"><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div class="gmail_extra"><div class="gmail_quote"><div>Also, just a hunch, but I suspect your hypothetical would never hold. Could you envision how the requirements for RandomWalkable might be such that it's possible to implement an efficient _default_ implementation of a random walk for any of several conforming data structures, but only one of these data structures is LinearWalkable, _and_ such a linear walk is efficient using another _default_implementation for an overlapping but not identical set of data structures? It's not mere trivia here, because the crux of your argument is that there exist default implementations that require copying and pasting into conforming types (and sufficiently efficient default implementations so that copying and pasting is appropriate rather than implementing a more efficient version). More likely in diamond problem scenarios, I think, colliding members are going to be properties or methods either without default implementations or than need to supply more efficient versions of default implementations anyway.</div></div></div></div></blockquote><div><br></div></span><div>Based on what? There is a reason the diamond problem has a name (and a wikipedia entry). Charles just said he ran into a problem like this. I have run into it in the past as well.</div></div></div></blockquote><div><br></div><div>Sure, and returning to my question above: could you share details about where you've run into this?</div></div><br></div></div>
</div></blockquote></div></div><div dir="auto"><div><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></div></blockquote></div>