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