[swift-evolution] [Proposal] Explicit Synthetic Behaviour
Vladimir.S
svabox at gmail.com
Tue Sep 12 12:02:57 CDT 2017
On 12.09.2017 18:09, Tony Allevato wrote:
>
>
> On Tue, Sep 12, 2017 at 3:32 AM Vladimir.S <svabox at gmail.com
> <mailto:svabox at gmail.com>> wrote:
>
> On 12.09.2017 0:35, Tony Allevato wrote:
> >
> >
> > On Mon, Sep 11, 2017 at 2:05 PM Vladimir.S via swift-evolution
> > <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>> wrote:
> >
> > On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
> > > I think I do understand Haravikk's argument (actually it seems quite
> > straightforward
> > > to me).
> > >
> > > An example should be:
> > >
> > > struct Foo : Equatable {
> > > var x: Int
> > > var cachedLabel: String? = nil
> > >
> > > init(x: Int) {
> > > self.x = x
> > > }
> > >
> > > mutating func label() {
> > > if let label = cachedLabel {
> > > return label
> > > }
> > > let label = calculateLabel()
> > > cachedLabel = label
> > > return cachedLabel
> > > }
> > > }
> > >
> > > var foo1 = Foo(x: 1)
> > > var foo2 = Foo(x: 1)
> > > foo1 == foo2 // true
> > > var label = foo1.label()
> > > foo1 == foo2 // now false, due to cachedString being falsely included
> in the
> > comparison
> > >
> > > The problem is that the developer was not required to implement the
> protocol
> > and so
> > > might forget it.
> > > The difference to other default implementations is that those use the
> protocol
> > itself
> > > as building blocks and so are correct with regards to the protocol's
> semantics,
> > > whereas the synthesized equality reaches deeply into the private
> innards of a
> > struct
> > > and therefore is much more likely to be wrong as in the example above.
> > >
> > > Why not just write
> > >
> > > *struct* Foo : *deriving* Equatable {...}
> > >
> > > to request the synthesized implementation?
> >
> > FWIW, +100. The same should be required for Codable. I support the opinion
> that
> > 'synthesized' methods differs from protocol-default-implementation in what
> 'kind' of
> > data they use: defined by protocol itself or internals of the conformed
> type. And
> > this can lead to more un-expected problems.
> >
> > If protocol is able to synthesize its requirements, it should require a
> > 'deriving'-like marker when type conforms to it to make it absolutely
> clear what
> > happens here. It would be not a confusion point, but clarify the intention
> to better
> > understand the code.
> >
> > Thinking about *future* custom protocols that could implement requirements
> in default
> > implementation by using macros/reflection, for me it seems like such
> protocol should
> > *also* somehow explicitly state that some requirements are
> auto-synthesized, probably
> > by conforming(derive) to some compiler-magic protocol 'AutoSynthesize'.
> > (i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')
> >
> > So each built-in protocol like Equatable/Hashable/Codable will conform to
> it, and
> > also, each custom "auto-synthesizeable" protocol - also should explicitly
> conform to
> > AutoSynthesize. So, when type conforms to it - such type should use
> 'deriving'-like
> > marker if auto-generation of methods is expected.
> >
> >
> > This doesn't align with how Swift views the role of protocols, though. One of the
> > criteria that the core team has said they look for in a protocol is "what generic
> > algorithms would be written using this protocol?" AutoSynthesize doesn't satisfy
> > that—there are no generic algorithms that you would write with AutoEquatable that
> > differ from what you would write with Equatable.
> >
>
> OK, got it, it was general thoughts, not exact proposal regarding the AutoSynthesize
> protocol. Probably it should be @autosynthesize directive for protocol when you
> define it or other 'marker', so when you conform to this protocol, you *can*
> explicitely use 'derived'-like keyword to make requirements auto-synthesized,
> otherwise you'll be asked by compiler for manual implementation.
>
>
> > I also have a question regarding future direction of 'exclusion' of fields
> from being
> > included into auto-generated implementation of
> Equatable/Hashable/Codable/other.
> >
> > If we'll have this 'deriving'-like marker, it seems naturally if we mark
> some member
> > with some kind of '@noderiving' marker, like here:
> >
> > struct Foo : deriving Equatable {
> > var x: Int
> > var y: Int
> > var z: Int
> > @noderiving var cachedLabel: String? = nil
> > }
> >
> > this @noderiving directive will work for protocols based on AutoSynthesize
> magic
> > protocol. I.e., if you construct your own protocol with
> auto-synthesizeable methods,
> > to be able to *know* which members should be 'excluded' for your
> implementation, you
> > should base your protocol on AutoSynthesize protocol.
> >
> >
> > This is something I mention in the original proposal, and I agree that it would be
> > nice to have added later since there are clear known use cases where it's
> important.
> >
> > However, the feature shouldn't be tied *specifically* to derived implementations
> > (meaning it shouldn't be named that way). What we're really talking about is
> > "transient" data—data that exists for the purposes of caching/performance/etc. but
> > which does not actually contribute to the thing's "value".
> >
> > The fact that transient data should not be ignored for equality, hashing, and
> > serialization just happens to align with the protocols that we auto-synthesize so
> > far, but it's not necessarily limited to those use cases. If an attribute is added
> > for something like this, it should be *semantic* rather than speak to
> implementation
> > details. In other words, it would be inappropriate to say "exclude this
> property from
> > synthesized operations", but it would be fine to say "this property is transient
> > data" and it just so happens that Equatable, Hashable, and Codable use that
> > information to control what they synthesize.
> >
> > All this is a subtle, but important, distinction. One day, when Swift has the
> ability
> > to introspect metadata about a type and its properties, someone may want to use a
> > hypothetical "transient" attribute for something wholly unrelated to synthesis.
>
> I see your points, but is it not possible that we want to exclude some property for
> Equatable but keep it for Codable, or vise-versa, for example? So, actually, IMO we
> need a way to exclude property from some specific protocol/protocols. Like
>
> @transient var ...
> @transient(for:Equatable) var ...
> @transient(for:Codable) var ...
> @transient(for:SomeOtherAuto) var ...
>
> And again, I'm not proposing some concrete syntax/keyword, but think we'll need(in
> future,yes, but IMO better to discuss now) a way to 'exclude' specific property from
> specific auto-synthesizeable protocol.
>
>
> It's possible, but we shouldn't think of it in terms of "exclude from a protocol".
> There are some different combinations to consider here:
>
> * Does it make sense to use a property in a synthesized Hashable but not in the
> synthesized Equatable? No, because of the contract between those two protocols. Such
> an exclusion would allow two equal values to hash to different values.
>
> * Does it make sense to use a property in a synthesized Equatable but not in the
> synthesized Hashable? Sure; if your data type is large you may only want to hash a
> subset of its properties. If that's the case, your hash function is probably simple
> enough that you can just override the property manually, which is more scalable than
> tagging all the non-hash properties individually.
>
> * Does it make sense to exclude a property used by synthesized Equatable/Hashable
> from synthesized Codable? Sure, maybe. If the property is truly transient cached data
> then it can easily be recomputed on demand, but you could argue that it's worth
> serializing if doing so is more efficient than performing the computation again.
>
> The key thing to note here is that "transient" shouldn't mean "exclude from
> implementations". "Transient", at least as I'm describing it, means "data
> that does not strictly contribute to something's notion of its 'value'". That's a
> semantic definition and it's up to the protocols themselves to decide how to
> interpret it. If there were a need for different "levels" of transience, then the
> attribute could be extended with more semantic information that lets the protocol
> decide what to do, or a new attribute could be introduced. The important thing is
> that you're saying "what does this property mean and how does it behave", not "which
> specific protocols can or can't do something with this property".
>
> Regarding "what about some future protocol", we can't really consider those
> realistically if we don't know what the semantics of that protocol are.
Well, seems like I'm missing something and just can't get it.
Currently, as I understand, we already have(see your reasoning above) two 'groups' of
protocols(Equatable/Hashable vs Codable) and so will need two kinds of 'transient'
directive. No?
And then, in _future_,
A) we can(who knows) have more built-in protocols that can auto-synthesize requirements
B) if some custom protocol can auto-synthesize requirements via macros system(for
example), it is logically that such protocol should be able to have a knowledge what
fields should be excluded.
Sorry, I still use 'excluded' as I don't understand(don't believe?) the idea of
"you're saying "what does this property mean and how does it behave".
Also, please consider this code:
struct S: Equatable, Codable
{
var x = 0
var y = 0
@transient var z = 0
...
// a number of lines here.
}
and this:
struct S: deriving Equatable, Codable
{
var x = 0
var y = 0
@transient var z = 0
...
// a number of lines here.
}
In second case it is clear that requirements for Equatable will be generated, and z
will not participate in it, but Codable is implemented in code manually and we don't
know if z will participate there.
In second case we have a much clear code that saying more than first case. This is
what I really like about the 'deriving'-like marker.
Vladimir.
>
>
> Just my 2 cents why I believe we need an explicit 'derived'-like keyword when we want
> auto-synthesized requirement for protocol:
>
> * This will not change the logic/behavior of 'normal' conformance to
> Equatable/Hashable, i.e. if you conform the type to them - you need to provide an
> implementation OR (new text in warning message will be added) "use 'derived' keyword
> to "auto-synthesize" these methods.
> I.e. auto-synthesize will be something separate, additional, that you can use if you
> want it, your clear choose.
> It will not interfere with your 'usual' model of protocol conformance.
>
> * You explicitly mark which protocol you want to be synthesized for you. For example,
> if I see "struct S: derived Equatable, Codable" - I understand that Equatable will be
> "generated" and Codable will be implemented manually in code.
>
> * This makes code more clean, more understandable by reader, less error-prone, more
> explicit on intention. The code *will* be better.
>
> * Without explicit 'derived'-like keyword, the code will be worse : less explicit
> about intention, more error-prone, hiding important details from reader, etc.
>
> * And the 'derived'-like keyword is good price to have better code in this case.
>
> Just my IMOs. Thank you for reading.
>
> Vladimir.
>
> >
> >
> > I hope this makes any sense :-)
> >
> > Vladimir.
> >
> > >
> > > -Thorsten
> > >
> > >
> > > Am 09.09.2017 um 19:42 schrieb Xiaodi Wu via swift-evolution
> > > <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>>:
> > >
> > >>
> > >> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution
> > >> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>> wrote:
> > >>
> > >>> On 9 Sep 2017, at 09:33, Xiaodi Wu <xiaodi.wu at gmail.com
> <mailto:xiaodi.wu at gmail.com>
> > <mailto:xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>>
> > >>> <mailto:xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>
> <mailto:xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>>>> wrote:
> > >>>
> > >>>
> > >>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution
> > >>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>> wrote:
> > >>>
> > >>>
> > >>>> On 9 Sep 2017, at 02:02, Xiaodi Wu <xiaodi.wu at gmail.com
> <mailto:xiaodi.wu at gmail.com>
> > <mailto:xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>>
> > >>>> <mailto:xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>
> <mailto:xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>>>> wrote:
> > >>>>
> > >>>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via
> > >>>> swift-evolution<swift-evolution at swift.org
> <mailto:swift-evolution at swift.org>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > >>>> <mailto:swift-evolution at swift.org
> <mailto:swift-evolution at swift.org>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>>wrote:
> > >>>>
> > >>>>
> > >>>>
> > >>>>> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution
> > >>>>> <swift-evolution at swift.org
> <mailto:swift-evolution at swift.org> <mailto:swift-evolution at swift.org
> <mailto:swift-evolution at swift.org>>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>> wrote:
> > >>>>>
> > >>>>>
> > >>>>>> On 7 Sep 2017, at 22:02, Itai Ferber
> <iferber at apple.com <mailto:iferber at apple.com>
> > <mailto:iferber at apple.com <mailto:iferber at apple.com>>
> > >>>>>> <mailto:iferber at apple.com <mailto:iferber at apple.com>
> <mailto:iferber at apple.com <mailto:iferber at apple.com>>>> 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:
> > >>>
> > >>> 1. 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.
> > >>
> > >>
> > >> You are against a default implementation for ==, i.e. an
> implementation that is
> > >> provided for you if you conform a type to the protocol and do nothing else
> > >> ("implicitly rather than explicitly"), and you are against the default
> > >> implementation being on the existing protocol Equatable ("retroactive
> > change"). So,
> > >> to summarize, what you are against is precisely a default
> implementation for
> > the ==
> > >> requirement on Equatable.
> > >>
> > >> This is the topic of discussion here; I am attempting to convince you
> that you
> > >> should be for rather than against these things.
> > >>
> > >>
> > >>> 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).
> > >>
> > >>
> > >> Right, one must consider the semantics of the specific protocol
> requirement
> > and ask
> > >> whether a reasonable default can be provided for it.
> > >>
> > >> 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).
> > >>
> > >>
> > >> I am confused why you are trying to argue in general terms about the
> universe of
> > >> all possible default implementations that use reflection. This is
> necessarily a
> > >> more difficult argument to make, and if it is to be convincing for all
> default
> > >> implementations it must also be convincing for the two specific protocol
> > >> requirements we are talking about here. Start small:
> > >>
> > >> We have agreed, as a community, that there is a reasonable default
> implementation
> > >> for Equatable.== when certain conditions are met (for value types only
> at the
> > >> moment, I believe). Namely, given two values of a type that has only
> Equatable
> > >> stored properties, those values are equal if their stored properties
> are all
> > equal.
> > >> The author of a new value type who wishes to make her type Equatable
> but chooses
> > >> not to implement a custom == then benefits from this default when all
> stored
> > >> properties are Equatable.
> > >>
> > >> 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.
> > >>
> > >>> 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 ==?
> > >>
> > >>> 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.
> > >>
> > >>
> > >> That is not the argument. The argument is that they are
> indistinguishable in the
> > >> sense that the author of a type who intends to supply a custom
> implementation but
> > >> neglects to do so will have a default implementation supplied for
> them. It is
> > >> plainly true that this is no more or less likely to happen simply
> because the
> > >> default implementation is synthesized.
> > >>
> > >>> 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.
> > >>
> > >> _______________________________________________
> > >> swift-evolution mailing list
> > >> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>
> > >> https://lists.swift.org/mailman/listinfo/swift-evolution
> > >>
> > >> _______________________________________________
> > >> swift-evolution mailing list
> > >> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>>
> > >> https://lists.swift.org/mailman/listinfo/swift-evolution
> > >
> > >
> > > _______________________________________________
> > > swift-evolution mailing list
> > > swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > > https://lists.swift.org/mailman/listinfo/swift-evolution
> > >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> <mailto:swift-evolution at swift.org <mailto:swift-evolution at swift.org>>
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> >
>
More information about the swift-evolution
mailing list