[swift-evolution] [Proposal] Explicit Synthetic Behaviour

Vladimir.S svabox at gmail.com
Wed Sep 13 13:47:42 CDT 2017


On 13.09.2017 20:48, Tony Allevato wrote:
> On Wed, Sep 13, 2017 at 10:21 AM Vladimir.S via swift-evolution 
> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> 
>     On 13.09.2017 19:08, Ondrej Barina via swift-evolution wrote:
>      > Maybe something like this as middle ground.
>      >
>      > protocol Equatable {
>      >      @syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool
>      > }
>      >
>      > protocol itself contains default implementation, but without real body.
>     Instead the
>      > function is marked that the real body is generated by compiler.
>      > There is explicit mentions of default impl (by compiler magic), but it does not
>      > affects users as they would still use protocol in normal way:
>      >
>      > struct Foo: Equatable { .... }
> 
>     Yes, I also thought about this. And personally for me it is also good solution, while
>     `struct S: Equatable {/*nothing*/}` will *still* lead to compiler's error or at least
>     warning about not implemented requirements.
>     So, I'll be explicit regarding my intention: do I want requirements to be
>     auto-generated or I want to do this manually.
> 
>     But still. If you see
> 
>     struct S: Equatable, Codable {
>         // a lot of lines
>     }
> 
>     you can't say right now if requirements for Equatable and/or Codable was implemented
>     manually or will be auto-generated without checking all the code of a type. This
>     knowledge can help to faster solve issues related to comparison/archiving.
>     So for me the best solution is still 'deriving'-like keyword, which adds clarity and
>     show intention without any boilerplate code:
> 
> 
> The sentences above apply equally to non-synthesized default protocol implementations:
> 
> struct S: Foo {
>    // a lot of lines
> }
> 
> I can't say if the requirements for Foo were implemented manually by S or by a 
> default implementation in Foo (which could be in a different module that I don't have 
> source access to) without checking all the code for S. So this can't be used as a 
> basis to rationalize special-casing synthesized implementations.

As was noted in this thread, some people believe that protocol synthesizing its 
requirements by accessing type's fields is of a different kind than 'usual' protocol 
with default implementation.
I belong to that camp. So, from my point of view, it is important to have 
'deriving'-like marker for 'auto-senthesizeable' protocols as described above.

Also, some 'usual' protocol Foo can have no default implementations at the moment of 
*writing* the code, but can have them at the moment of *compilation* via protocol 
extension in separate file in project. So it is not possible to require similar 
marker for such protocol.
But Equatable/Hashable/Codable protocols has auto-generation feature already at the 
moment of writing the code and we can request that marker.

Vladimir.

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


More information about the swift-evolution mailing list