On 12.09.2017 18:09, Tony Allevato wrote:


On Tue, Sep 12, 2017 at 3:32 AM Vladimir.S <sva...@gmail.com <mailto:sva...@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@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>>>:
     >      >
     >      >>
     >      >> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution
     >      >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>>> 
wrote:
     >      >>
     >      >>>     On 9 Sep 2017, at 09:33, Xiaodi Wu <xiaodi...@gmail.com
    <mailto:xiaodi...@gmail.com>
     >     <mailto:xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>>
     >      >>>     <mailto:xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>
    <mailto:xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>>>> wrote:
     >      >>>
     >      >>>
     >      >>>     On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution
     >      >>>     <swift-evolution@swift.org 
<mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>>> 
wrote:
     >      >>>
     >      >>>
     >      >>>>         On 9 Sep 2017, at 02:02, Xiaodi Wu <xiaodi...@gmail.com
    <mailto:xiaodi...@gmail.com>
     >     <mailto:xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>>
     >      >>>>         <mailto:xiaodi...@gmail.com 
<mailto:xiaodi...@gmail.com>
    <mailto:xiaodi...@gmail.com <mailto:xiaodi...@gmail.com>>>> wrote:
     >      >>>>
     >      >>>>         On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via
     >      >>>>         swift-evolution<swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >      >>>>         <mailto:swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>
     >     <mailto:swift-evolution@swift.org 
<mailto:swift-evolution@swift.org>>>>wrote:
     >      >>>>
     >      >>>>
     >      >>>>
     >      >>>>>             On Sep 8, 2017, at 12:46 AM, Haravikk via 
swift-evolution
     >      >>>>>             <swift-evolution@swift.org
    <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org
    <mailto:swift-evolution@swift.org>>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>>> 
wrote:
     >      >>>>>
     >      >>>>>
     >      >>>>>>             On 7 Sep 2017, at 22:02, Itai Ferber
    <ifer...@apple.com <mailto:ifer...@apple.com>
     >     <mailto:ifer...@apple.com <mailto:ifer...@apple.com>>
     >      >>>>>>             <mailto:ifer...@apple.com 
<mailto:ifer...@apple.com>
    <mailto:ifer...@apple.com <mailto:ifer...@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@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>>
     >      >> https://lists.swift.org/mailman/listinfo/swift-evolution
     >      >>
     >      >> _______________________________________________
     >      >> swift-evolution mailing list
     >      >> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >     <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>>
     >      >> https://lists.swift.org/mailman/listinfo/swift-evolution
     >      >
     >      >
     >      > _______________________________________________
     >      > swift-evolution mailing list
     >      > swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>
     >      > https://lists.swift.org/mailman/listinfo/swift-evolution
     >      >
     >     _______________________________________________
     >     swift-evolution mailing list
     > swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    <mailto:swift-evolution@swift.org <mailto: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

Reply via email to