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>>>:
>
>>
>> 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>>>
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>>> 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>>>
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>>>
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>>>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>>>
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>>>
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>>
>> 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>
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution