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. Gwendal > Le 9 sept. 2017 à 15:26, Gwendal Roué <[email protected]> a écrit : > > Hello Haravikk, > > I'lm worried that you fail at preventing a real problem. May I suggest a > change in your strategy? > > Sometimes, sample code greatly helps turning subtle ideas into blatant > evidence. After all, subtleties are all about corner cases, and corner cases > are the blind spots of imagination. What about giving that little something > that would help your readers grasp your arguments? > > I don't quite know what example you will provide, but I could suggest the > exhibition of a practical problem with Equatable synthesis. We'll know better > if the problem can arise in the Standard lib, in third-party libraries, at > application level, or at several scales at the same time. It would also be > nice to see your solution to the problem, that is to say an alternative that > still provides code synthesis for developers that want to opt in the feature, > but avoids the caveat of the initial example. I hope this would greatly help > the discussion move forward. > > Last general comment about the topic: if Haravikk is right, and that code > synthesis should indeed be explicit, then that wouldn't be such a shame. > > My two cents, > Gwendal Roué > > >> Le 9 sept. 2017 à 13:41, Haravikk via swift-evolution >> <[email protected] <mailto:[email protected]>> a écrit : >> >>> >>> On 9 Sep 2017, at 09:33, Xiaodi Wu <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> >>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>>> On 9 Sep 2017, at 02:02, Xiaodi Wu <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution >>>> <[email protected] <mailto:[email protected]>> wrote: >>>> >>>> >>>>> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution >>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>> >>>>> >>>>>> On 7 Sep 2017, at 22:02, Itai Ferber <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>> protocol Fooable : Equatable { // Equatable is just a simple example >>>>>> var myFoo: Int { get } >>>>>> } >>>>>> >>>>>> extension Fooable { >>>>>> static func ==(_ lhs: Self, _ rhs: Self) -> Bool { >>>>>> return lhs.myFoo == rhs.myFoo >>>>>> } >>>>>> } >>>>>> >>>>>> struct X : Fooable { >>>>>> let myFoo: Int >>>>>> let myName: String >>>>>> // Whoops, forgot to give an implementation of == >>>>>> } >>>>>> >>>>>> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // >>>>>> true >>>>>> This property is necessary, but not sufficient to provide a correct >>>>>> implementation. A default implementation might be able to assume >>>>>> something about the types that it defines, but it does not necessarily >>>>>> know enough. >>>>> >>>>> Sorry but that's a bit of a contrived example; in this case the protocol >>>>> should not implement the equality operator if more information may be >>>>> required to define equality. It should only be implemented if the >>>>> protocol is absolutely clear that .myFoo is the only part of a Fooable >>>>> that can or should be compared as equatable, e.g- if a Fooable is a >>>>> database record and .myFoo is a primary key, the data could differ but it >>>>> would still be a reference to the same record. >>>>> >>>>> To be clear, I'm not arguing that someone can't create a regular default >>>>> implementation that also makes flawed assumptions, but that >>>>> synthesised/reflective implementations by their very nature have to, as >>>>> they cannot under every circumstance guarantee correctness when using >>>>> parts of a concrete type that they know nothing about. >>>> >>>> You can’t argue this both ways: >>>> If you’re arguing this on principle, that in order for synthesized >>>> implementations to be correct, they must be able to — under every >>>> circumstance — guarantee correctness, then you have to apply the same >>>> reasoning to default protocol implementations. Given a default protocol >>>> implementation, it is possible to come up with a (no matter how contrived) >>>> case where the default implementation is wrong. Since you’re arguing this >>>> on principle, you cannot reject contrived examples. >>>> If you are arguing this in practice, then you’re going to have to back up >>>> your argument with evidence that synthesized examples are more often wrong >>>> than default implementations. You can’t declare that synthesized >>>> implementations are by nature incorrect but allow default implementations >>>> to slide because in practice, many implementations are allowable. There’s >>>> a reason why synthesis passed code review and was accepted: in the >>>> majority of cases, synthesis was deemed to be beneficial, and would >>>> provide correct behavior. If you are willing to say that yes, sometimes >>>> default implementations are wrong but overall they’re correct, you’re >>>> going to have to provide hard evidence to back up the opposite case for >>>> synthesized implementations. You stated in a previous email that "A >>>> synthesised/reflective implementation however may return a result that is >>>> simply incorrect, because it is based on assumptions made by the protocol >>>> developer, with no input from the developer of the concrete type. In this >>>> case the developer must override it in to provide correct behaviour." — if >>>> you can back this up with evidence (say, taking a survey of a large number >>>> of model types and see if in the majority of cases synthesized >>>> implementation would be incorrect) to provide a compelling argument, then >>>> this is something that we should in that case reconsider. >>>> >>>> Well put, and I agree with this position 100%. However, to play devil's >>>> advocate here, let me summarize what I think Haravikk is saying: >>>> >>>> I think the "synthesized" part of this is a red herring, if I understand >>>> Haravikk's argument correctly. Instead, it is this: >>>> >>>> (1) In principle, it is possible to have a default implementation for a >>>> protocol requirement that produces the correct result--though not >>>> necessarily in the most performant way--for all possible conforming types, >>>> where by conforming we mean that the type respects both the syntactic >>>> requirements (enforced by the compiler) and the semantic requirements >>>> (which may not necessarily be enforceable by the compiler) of the protocol >>>> in question. >>>> >>>> (2) However, there exist *some* requirements that, by their very nature, >>>> cannot have default implementations which are guaranteed to produce the >>>> correct result for all conforming types. In Haravikk's view, no default >>>> implementations should be provided in these cases. (I don't necessarily >>>> subscribe to this view in absolute terms, but for the sake of argument >>>> let's grant this premise.) >>>> >>>> (3) Equatable, Hashable, and Codable requirements are, by their very >>>> nature, such requirements that cannot have default implementations >>>> guaranteed to be correct for all conforming types. Therefore, they should >>>> not have a default implementation. It just so happens that a default >>>> implementation cannot currently be written in Swift itself and must be >>>> synthesized, but Haravikk's point is that even if they could be written in >>>> native Swift through a hypothetical reflection facility, they should not >>>> be, just as many other protocol requirements currently could have default >>>> implementations written in Swift but should not have them because they >>>> cannot be guaranteed to produce the correct result. >>>> >>>> My response to this line of argumentation is as follows: >>>> >>>> For any open protocol (i.e., a protocol for which the universe of possible >>>> conforming types cannot be enumerated a priori by the protocol designer) >>>> worthy of being a protocol by the Swift standard ("what useful thing can >>>> you do with such a protocol that you could not without?"), any >>>> sufficiently interesting requirement (i.e., one for which user ergonomics >>>> would measurably benefit from a default implementation) either cannot have >>>> a universally guaranteed correct implementation or has an implementation >>>> which is also going to be the most performant one (which can therefore be >>>> a non-overridable protocol extension method rather than an overridable >>>> protocol requirement with a default implementation). >>> >>> You're close, but still missing key points: >>> >>> I am not arguing that features like these should not be provided, but that >>> they should not be provided implicitly, and that the developer should >>> actually be allowed to request them. That is exactly what this proposal is >>> about, yet no matter what I say everyone seems to be treating me like I'm >>> against these features entirely; I am not. >>> >>> You are entirely against Equatable having a default implementation for ==. >>> This is unequivocally stated. Others favor such a default implementation >>> and feel that in the absence of a way to spell this in Swift itself, it >>> should be magic for the time being. For the purposes of this argument it >>> really is not pertinent that you are not also against something else; >>> you're asking us to discuss why you are against a particular thing that >>> others are for. >> >> FFS, how much clearer can I make this? I AM NOT AGAINST THE FEATURE. >> >> What I am against is the way in which it is being provided implicitly rather >> than explicitly, in particular as a retroactive change to existing protocols >> in a way that introduces potential for bugs that are currently impossible, >> but also in general. >> >>> As repeatedly answered by others, nothing here is specific to synthesized >>> default implementations, as more powerful reflection will gradually allow >>> them to be non-synthesised. >> >> And as repeatedly stated by me; I am not treating synthesised vs. run-time >> reflection any differently, I specifically included both in the original >> proposal. >> >>> As pointed out very cogently by Itai, you assert but offer no evidence, >>> either in principle or empirically, that going too far by reflection is >>> worse than going not far enough without reflection in terms of likelihood >>> of a default implementation being inappropriate for conforming types. >> >> As I have also repeatedly pointed out it is not an issue of "not going far >> enough" vs. "going too far"; if a default implementation lacks information >> then it should not be provided, doing so regardless is a flaw in the >> protocol design and not something that this proposal attempts to address (as >> such a thing is likely impossible). >> >> Reflective implementations necessarily go too far, because they literally >> know nothing about the concrete type with any certainty, except for the >> properties that are defined in the protocol (which do not require reflection >> or synthesis in the first place). >> >> 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. >> >>> 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. >> >>> And all of this continues to be a side-issue to the fact that in the >>> specific case of Equatable/Hashable, which thus far has gone ignored, is >>> that bolting this on retroactively to an existing protocol hides bugs. The >>> issue of reflective default implementations is less of a concern on very >>> clearly and well defined new protocols, though I still prefer more, rather >>> than less, control, but in the specific case of existing protocols this >>> fucking about with behaviours is reckless and foolish in the extreme, yet >>> no-one on the core teams seems willing or able to justify it, which only >>> opens much wider concerns (how am I to have any faith in Swift's >>> development if the core team can't or won't justify the creation of new >>> bugs?). >>> >>> This has emphatically not gone ignored, as I have myself responded to this >>> point in an earlier thread in which you commented, as well as many others. >>> Crucially, no existing conforming type changes its behavior, as they have >>> all had to implement these requirements themselves. And as I said to you >>> already, the addition of a synthesized default implementation no more >>> "hides bugs" going forward than the addition of a non-synthesized default >>> implementation to an existing protocol, and we do that with some frequency >>> without even Swift Evolution review. >> >> Feel free to a supply a non-synthesised default implementation for Equatable >> without the use of reflection. Go-on, I'll wait. >> You insist on suggesting these are the same thing, yet if you can't provide >> one then clearly they are not. >> >>> 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. >> _______________________________________________ >> swift-evolution mailing list >> [email protected] <mailto:[email protected]> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
