On Wed, Sep 13, 2017 at 10:21 AM Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:
> On 13.09.2017 19:08, Ondrej Barina via swift-evolution wrote: > > Maybe something like this as middle ground. > > > > protocol Equatable { > > @syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool > > } > > > > protocol itself contains default implementation, but without real body. > Instead the > > function is marked that the real body is generated by compiler. > > There is explicit mentions of default impl (by compiler magic), but it > does not > > affects users as they would still use protocol in normal way: > > > > struct Foo: Equatable { .... } > > Yes, I also thought about this. And personally for me it is also good > solution, while > `struct S: Equatable {/*nothing*/}` will *still* lead to compiler's error > or at least > warning about not implemented requirements. > So, I'll be explicit regarding my intention: do I want requirements to be > auto-generated or I want to do this manually. > > But still. If you see > > struct S: Equatable, Codable { > // a lot of lines > } > > you can't say right now if requirements for Equatable and/or Codable was > implemented > manually or will be auto-generated without checking all the code of a > type. This > knowledge can help to faster solve issues related to comparison/archiving. > So for me the best solution is still 'deriving'-like keyword, which adds > clarity and > show intention without any boilerplate code: > The sentences above apply equally to non-synthesized default protocol implementations: struct S: Foo { // a lot of lines } I can't say if the requirements for Foo were implemented manually by S or by a default implementation in Foo (which could be in a different module that I don't have source access to) without checking all the code for S. So this can't be used as a basis to rationalize special-casing synthesized implementations. > > struct S: Equatable, deriving Codable { > // all clear: > // manually implemented Equatable > // auto-generated Codable > > // a lot of lines > } > > Vladimir. > > > > > Ondrej B. > > > > On Wed, Sep 13, 2017 at 4:14 PM, Haravikk via swift-evolution > > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: > > > > > >> On 13 Sep 2017, at 03:26, Xiaodi Wu <xiaodi...@gmail.com > >> <mailto:xiaodi...@gmail.com>> wrote: > >> > >> On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via > >> swift-evolution<swift-evolution@swift.org <mailto: > swift-evolution@swift.org>>wrote: > >> > >> > >>> On 12 Sep 2017, at 12:08, Xiaodi Wu <xiaodi...@gmail.com > >>> <mailto:xiaodi...@gmail.com>> wrote: > >>> > >>>> On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution > >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> > wrote: > >>>> > >>>> See, this is another flawed assumption; you are assuming > that > >>>> omitting a custom implementation of == is always > intentional rather > >>>> than an oversight, which is not guaranteed. This is one > of my gripes > >>>> with the retroactive change to Equatable, as it is > >>>> currently*impossible* to omit an implementation. > >>> > >>> > >>> Again, this applies equally to the addition of _any_ default > >>> implementation. And again, such changes don’t even require > Swift Evolution > >>> approval. > >> > >> So what? Because the Swift Evolution process is currently > deficient we > >> should just give up on discussing problems with features and > the language > >> altogether? > >> > >> > >> I don't claim that it's a deficiency; I claim it's reflective of > Swift's > >> opinionated take on default implementations. Are you, after all, > saying that > >> you have a problem with the addition of _any_ default > implementation to an > >> existing protocol? If so, this conversation isn't about > synthesis/reflection at > >> all. > > > > No, and you should know that by now. I suggest actually reading some > of what I > > have written as I am sick of repeating myself. > > > >>>>>> And precisely what kind of "evidence" am I expected to > give? This > >>>>>> is a set of features that*do not exist yet*, I am > trying to argue > >>>>>> in favour of an explicit end-developer centric opt-in > rather than > >>>>>> an implicit protocol designer centric one. Yet no-one > seems > >>>>>> interested in the merits of allowing developers to > choose what they > >>>>>> want, rather than having implicit behaviours appear > potentially > >>>>>> unexpectedly. > >>>>> > >>>>> Both options were examined for Codable and for > Equatable/Hashable. > >>>>> The community and core team decided to prefer the > current design. At > >>>>> this point, new insights that arise which could not be > anticipated > >>>>> at the time of review could prompt revision. However, so > far, you > >>>>> have presented arguments already considered during > review. > >>>> > >>>> And so far all I have heard about this is how it was > "decided"; > >>>> no-one seems interested in showing how any of these > concerns were > >>>> addressed (if at all), so as far as I can tell they were > not, or they > >>>> were wilfully ignored. > >>> > >>> > >>> They were addressed by being considered. > >> > >> And yet no-one can apparently summarise what those > "considerations" might > >> be, suggesting that they were either *not* considered at all, > or that the > >> "consideration" was so weak that no-one is willing to step > forward to > >> defend it. Either way it is not sufficient by any reasonable > measure. > >> > >> If I were to run over your foot in my car, would you be happy > to accept > >> that I "considered" it first? > >> > >> > >> How do you mean? People wrote in with their opinions. Then, taking > into account > >> the community's response, the proposal was approved. > > > > I mean because not once have you summarised what these alleged > "considerations" > > were; if they exist then you should be able do so, yet all I am > hearing is "it > > was considered", which frankly is not an argument at all as it is > entirely > > without substance. > > > > If it was genuinely considered then someone should be able to say > what points > > were considered and what conclusions were reached and why. And even > if there > > *was* an earlier decision, that doesn't necessarily make it right. > We are > > discussing it now, and it is clear that any decision that has been > made has been > > made poorly at best. > > > > And if you're talking about the discussion on Equatable/Hashable > specifically, > > I'm afraid your memory of the "considerations" is radically > different to mine; as > > the concerns I raised were essentially ignored, as not a single > person gave a > > justification more substantial than "but, but Codable!" which > frankly isn't a > > justification at all. > > > >>>>>> Therefore, your argument reduces to one about which > default > >>>>>> implementations generally ought or ought not to be > >>>>>> provided--that is, that they ought to be provided > only when > >>>>>> their correctness can be guaranteed for all (rather > than almost > >>>>>> all) possible conforming types. To which point I > sketched a > >>>>>> rebuttal above. > >>>>> > >>>>> If a protocol defines something, and creates a > default > >>>>> implementation based only upon those definitions > then it must by > >>>>> its very nature be correct. A concrete type may > later decided to > >>>>> go further, but that is a feature of the concrete > type, not a > >>>>> failure of the protocol itself which can function > correctly > >>>>> within the context it created. You want to talk > evidence, yet > >>>>> there has been no example given that proves > otherwise; thus far > >>>>> only Itai has attempted to do so, but I have already > pointed out > >>>>> the flaws with that example. > >>>>> > >>>>> The simple fact is that a default implementation may > either be > >>>>> flawed or not within the context of the protocol > itself; but a > >>>>> reflective or synthetic implementation by its very > nature goes > >>>>> beyond what the protocol defines and so is > automatically flawed > >>>>> because as it does not rely on the end-developer to > confirm > >>>>> correctness, not when provided implicitly at least. > >>>>> > >>>>> > >>>>> Again, if it applies generally, it must apply > specifically. What is > >>>>> "automatically flawed" about the very reasonable > synthesized default > >>>>> implementation of ==? > >>>> > >>>> It makes the assumption that every equatable property of > a type is > >>>> necessarily relevant to its equality. > >>> > >>> > >>> No necessarily, only provisionally and rebuttably. If it’s not > the case, > >>> override the default. > >> > >> So… entirely unlike standard default implementations > >> which*cannot* "provisionally" assume something is relevant at > all, > >> > >> > >> Why not? > > > > Because they can only act upon properties/methods that they > themselves (or a > > parent protocol) define. FFS, what is so unclear about that? Or are > you arguing > > on this subject without every having actually used a protocol before? > > > >> thereby making them entirely different from > synthesised/reflective > >> implementations! > >> > >> I'm sorry, but you keep trying to argue that they're the same, > but then > >> admitting that they're not. You can't have it both ways. > >> > >> > >> Well, certainly, synthesized default implementations differ from > >> non-synthesized ones in key respects. However, they do not differ > in terms of > >> the user experience of conforming to the protocol and having to > override the > >> default. > > > > Except that that's not true at all, is it? > > > > Synthesised default implementations go much further in how they > attempt (and > > potentially fail) to implement those defaults, and in the specific > case of > > Equatable/Hashable they are fully implementing a protocol without a > single > > property of method being raised as a requirement; they are utterly > different at a > > fundamental level, no amount of mental contortion changes that fact. > > > >>>> Consider for example if a type stores a collection index > for > >>>> performance reasons; this isn't an intrinsic part of the > type, nor > >>>> relevant to testing equality, yet this default > implementation will > >>>> treat it as such because it*knows nothing about the > concrete type's > >>>> properties*. If a protocol does not define a property > then any action > >>>> taken upon such a property is necessarily based upon an > assumption; > >>>> just because it might be fine some of the time, does not > make it any > >>>> less flawed. > >>>> > >>>> The big difference here between explicit and implicit > synthetic > >>>> implementations is where this assumption originates; if a > method is > >>>> synthesised implicitly then the assumption is made by the > protocol > >>>> designer alone, with no real involvement by the end > developer. If I > >>>> explicitly opt-in to that default however I am signalling > to the > >>>> protocol that it is okay to proceed. In the former case > the > >>>> assumption is unreasonable, in the latter it is explicitly > >>>> authorised. It is a difference between "I want to make > the decision > >>>> on what's correct" and "I am happy for you (the protocol > designer) to > >>>> decide". > >>>> > >>>> Right now, when I conform to Equatable, it is a > declaration of "I > >>>> will implement this", but with this retroactive implicit > change it is > >>>> now a declaration of "implement this for me", these are > two entirely > >>>> different things. Consider; what if I'm working on a > piece of code > >>>> that requires types to be Equatable, but one of the types > I'm using > >>>> currently isn't, so I quickly throw Equatable conformance > onto it and > >>>> go back to what I was doing, with the intention of > completing > >>>> conformance later. With this change that type may now > receive a > >>>> default implementation that is wrong, and I've lost the > safety net > >>>> that currently exists. > >>> > >>> > >>> Right now, it still wouldn’t compile, so I don’t see why you > would do > >>> that. In the future, if you want to make it not compile, there > is nothing > >>> stopping you from conforming to a non-existent > “NotYetEquatable”. This was > >>> something that you asked about earlier and it was answered. > >> > >> So your solution is to intentionally write invalid code to work > around the > >> fact that a feature is being implemented badly? > >> > >> > >> You stated a use case where you *want* the compiler to stop your > code from > >> compiling by stating a conformance to Equatable without > implementing its > >> requirements. You then stated that the major problem you have with > synthesized > >> `==` is that the compiler will now use a default implementation > that you might > >> forget about instead of stopping compilation. Therefore, I > demonstrated how you > >> could continue to have the compiler stop your code from compiling. > It's not my > >> solution that is intentionally writing invalid code; your stated > aim was to be > >> able to do so. > > > > My stated aim was nothing of the sort. > > > > I was pointing out that right now conforming to Equatable means > something > > entirely different from what it will mean in future if this idiotic > change makes > > it into release. Please actually read what I write before deciding > for yourself > > what my 'stated aim' is. > > > > I am *not* asking for workarounds to circumvent a ridiculously > flawed change to > > the language, I am arguing why it is flawed and must be changed. If > I wanted a > > workaround I'd do what I'm now seriously considering, which is > ditching Swift > > completely, as I will not use a language if I can no longer trust > the team > > developing it or the decisions that they make. > > > >>>> A non-synthesised/reflective implementation cannot > strictly be > >>>> incorrect, because as long as it is implemented properly > it will > >>>> always be correct within the context of the protocol > itself. It may > >>>> not go quite as far as an end developer might want, but > that is > >>>> because they want to add something onto the protocol, not > because the > >>>> protocol is wrong. > >>>> > >>>> A synthesised/reflective implementation differs because > if it goes > >>>> too far it is wrong not only within the context of the > concrete type, > >>>> but also the protocol itself, it is simply incorrect. > >>> > >>> > >>> Again, this is an assertion that misses the mark. If the > default > >>> implementation is unsuitable for a type, it’s unsuitable > whether it > >>> “doesn’t go quite as far” or “goes too far.” > >> > >> Because not going quite far enough is not a failure of the > protocol, as > >> protocols by their very nature can only go as far as what they > define. If a > >> protocol Foo defines two properties, a method which uses those > two > >> properties correctly, then the method is correct. A developer > of a concrete > >> type might want to add more information or tailor the > behaviour, but that > >> doesn't make the default implementation incorrect, it's just > considering > >> the type only within the context of being an instance of Foo. > >> > >> Going too far is the opposite; it's the protocol designer > messing around > >> with stuff they do not define at all. It's only ever right by > chance, as > >> it's operating within the context of the concrete type, about > which the > >> protocol does not know anything with certainty. > >> > >> > >> Yes, you have defined "not going far enough" and "going too far" > based on > >> whether an implementation uses only protocol requirements or not. > However, you > >> haven't at all demonstrated why this distinction is at all > meaningful in terms > >> of the issue you describe with a user conforming to a protocol. If > there is a > >> default implementation, either it returns the expected result for > the > >> conforming type or it does not--those are the only two choices. Are > you arguing > >> that, empirically, the default implementation for Equatable will > more often be > >> unsuitable for conforming types? If so, what's your evidence? > > > > What's yours? If this issue was as "considered" as you constantly > claim then > > where is the evidence that there is no meaningful distinction? > Surely such > > evidence exists, or else the issue hasn't been considered at all, > has it? > > > > Frankly I am sick of being asked to provide evidence when you are > seemingly > > unwilling to do anything in return, especially when you have > conveniently ignored > > every single example that I have already given. > > > > It cuts both ways; you claim that "going too far" and "not going far > enough" are > > the same thing? Well prove it. > > > >>> You state but do not give any rationale for the claim that the > former is > >>> not wrong in some context while the latter is always wrong. > >>> > >>> By this line of argumentation, you’d be perfectly content if > instead we > >>> simply had the default implementation of == as “return true” > because it > >>> would be somehow not wrong. > >> > >> Only if return true were a reasonable default to give in the > context of the > >> protocol, which it clearly is not, as it's not performing any > kind of > >> comparison of equality. > >> > >> > >> Sure it is; `return true` satisfies all the semantic requirements > for equality: > >> reflexivity, symmetry, transitivity; and, in the context of the > protocol which > >> only provides for this one facility (determination of equality or > inequality), > >> any two instances that compare equal _are_ completely > interchangeable "within > >> the context of the protocol itself," as you would say. > > > > The purpose of Equatable is to identify types that can be compared > for equality; > > returning true does not satisfy that aim because no such comparison > is occurring, > > so your example is intentionally ridiculous. Even a less contrived > example such > > as comparing memory addresses doesn't fulfil the purpose of > Equatable, which is > > all about comparing equality of different instances that might still > be the same. > > > >>>>> Put another way, what the proposal about synthesizing > >>>>> implementations for Equatable and Hashable was about > can be > >>>>> thought of in two parts: (a) should there be default > >>>>> implementations; and (b) given that it is impossible > to write > >>>>> these in Swift, should we use magic? Now, as I said > above, > >>>>> adding default implementations isn't (afaik) even > considered an > >>>>> API change that requires review on this list. > Really, what > >>>>> people were debating was (b), whether it is worth it > to > >>>>> implement compiler-supported magic to make these > possible. Your > >>>>> disagreement has to do with (a) and not (b). > >>>> > >>>> Wrong. The use of magic in this case produces > something else > >>>> entirely; that's the whole point. It is*not the > same*, otherwise > >>>> it wouldn't be needed at all. It doesn't matter if > it's compiler > >>>> magic, some external script or a native macro, > ultimately they > >>>> are all doing something with a concrete type that is > currently > >>>> not possible. > >>>> > >>>> And once again;*I am not arguing against a default > implementation > >>>> that cuts boilerplate*, I am arguing against it being > implicit. > >>>> What I want is to be the one asking for it, because > it is not > >>>> reasonable to assume that just throwing it in there > is always > >>>> going to be fine, because it quite simply is not. > >>>> > >>>> > >>>> If you have to ask for it, then it's not a default. You > *are* against > >>>> a default implementation. > >>> > >>> A default implementation is an implementation that I, as > the concrete > >>> type developer, do not have to provide myself. If you want > default to > >>> mean only "automatic" then your attempt to pigeon-hole > what I am > >>> arguing is incorrect, because what I am arguing is then > neither about > >>> default implementations nor the means of actually > implementing it, but > >>> something else entirely. > >>> > >>> But as far as I'm concerned it still absolutely still a > default > >>> implementation whether it is requested or not; the > difference is I, as > >>> the end developer, am able to refine what type of defaults > that I want. > >>> > >>> > >>> The word “default” indicates something that arises in the > absence of a > >>> user indication otherwise. > >> > >> Then this proposal is just for a different mechanism for > "indicating > >> otherwise". > >> > >> You keep trying to argue that a synthesised/reflective default > >> implementation is the same as a normal default implementation, > yet you seem > >> to be consistently forgetting that even if that is true without > this > >> proposal, that the very proposal itself is to change that, > effectively > >> causing a category of default implementation to become > explicitly > >> opted-into, rather than implicitly. They're still > implementations that will > >> be provided automatically, just only when they are permitted to > do-so. > >> > >> > >> So to be clear, you are *against* them being the *default*: you > wish them to be > >> the *otherwise*. > > > > You seem to be insisting upon a narrow definition of default; what I > want is > > control over which types of default implementations are provided. > Just because > > they must be opted-into explicitly does not stop them being > "default", as they > > are still implementations that I myself do not need to implement. > The difference > > is that I want to actually *want* them rather than have provided > through > > potentially flimsy assumptions made by a protocol designer. Just > because there's > > an extra step doesn't make them any less automatic, otherwise having > to conform > > to a protocol in the first place would also prevent them from being > defaults. > > > > Asking *for* something is more like a middle-ground between the two; > the > > synthetic implementations are still possible defaults, they just > aren't provided > > unless you allow them, while omitting the necessary > keyword/attribute prevents > > them being used. > > > >>>> On 9 Sep 2017, at 23:17, Gwendal Roué < > gwendal.r...@gmail.com > >>>> <mailto:gwendal.r...@gmail.com>> wrote: > >>>> > >>>> All right, I'll be more positive: our science, IT, is a > >>>> *constructive* science, by *essence*. If there is a > problem, there > >>>> must be a way to show it. > >>>> It you can't, then there is no problem. > >>> > >>> You mean just as I have asked for examples that prove > >>> non-synthetic/reflective default implementations are as > dangerous as > >>> synthetic/reflective ones? Plenty have suggested this is > the case yet > >>> no reasonable examples of that have been given either. > >>> > >>> However, examples highlighting problems with the > synthesised behaviour > >>> are simple: > >>> > >>> structFoo :Equatable{vardata:String}// Currently an > error, won't > >>> be in future > >>> > >>> > >>> Or something a bit more substantial: > >>> > >>> structKeyPair :Equatable{ > >>> staticvarcount:Int=0 > >>> > >>> varcount:Int > >>> letkey:String// This is the only property that should > be equatable > >>> varvalue:String > >>> > >>> init(key:String, value:String) { > >>> letcount =KeyPair.count&+1 > >>> KeyPair.count= count;self.count= count > >>> self.key= key;self.value= value > >>> } > >>> } > >>> > >>> Here the only important property in the key pair is the > key, the value > >>> isn't important (only the keys are to be considered > unique) and the > >>> count is just a throwaway value. The synthesised default > >>> implementation for this concrete type will therefore be > completely > >>> wrong, likewise for Hashable, which will likely produce > radically > >>> different results for instances that should be the same. > >> > >> I notice that despite asking endlessly for examples, the ones > I've given > >> are being ignored. In future I shall remind people asking for > examples > >> where they can shove them. > > > > And once again, totally ignored. You seem to love asking for > "evidence" but why > > exactly should I bother giving anything if you ignore it when I try > to? > > > > _______________________________________________ > > swift-evolution mailing list > > swift-evolution@swift.org <mailto:swift-evolution@swift.org> > > https://lists.swift.org/mailman/listinfo/swift-evolution > > <https://lists.swift.org/mailman/listinfo/swift-evolution> > > > > > > > > > > _______________________________________________ > > 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 >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution