<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Wed, Sep 13, 2017 at 8:41 AM Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; 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 7:14, Xiaodi Wu via swift-evolution wrote:<br>
&gt;<br>
&gt; On Tue, Sep 12, 2017 at 22:07 Tony Allevato &lt;<a href="mailto:tony.allevato@gmail.com" target="_blank">tony.allevato@gmail.com</a><br>
&gt; &lt;mailto:<a href="mailto:tony.allevato@gmail.com" target="_blank">tony.allevato@gmail.com</a>&gt;&gt; wrote:<br>
&gt;<br>
&gt;     On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a><br>
&gt;     &lt;mailto:<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;&gt; wrote:<br>
&gt;<br>
&gt;         On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via swift-evolution<br>
&gt;         &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt; wrote:<br>
&gt;<br>
&gt;             Good arguments, Tony, you have convinced me on all points. Transient is<br>
&gt;             the way to go. Thank you for your patience!<br>
&gt;<br>
&gt;<br>
&gt;         On many points, I agree with Tony, but I disagree that &quot;transient&quot; addresses<br>
&gt;         the issue at hand. The challenge being made is that, as Gwendal puts it, it&#39;s<br>
&gt;         _unwise_ to have a default implementation, because people might forget that<br>
&gt;         there is a default implementation. &quot;Transient&quot; only works if you remember<br>
&gt;         that there is a default implementation, and in that case, we already have a<br>
&gt;         clear syntax for overriding the default.<br>
&gt;<br>
&gt;<br>
&gt;     RightБ─■I hope it hasn&#39;t sounded like I&#39;m conflating the two concepts completely.<br>
&gt;     The reason I brought up &quot;transient&quot; is because nearly all of the &quot;risky&quot; examples<br>
&gt;     being cited so far have been of the variety &quot;I have a type where some properties<br>
&gt;     happen to be Equatable but shouldn&#39;t be involved in equality&quot;, so my intention<br>
&gt;     has been to show that if we have a better solution to that specific problem<br>
&gt;     (which is, related to but not the same as the question at hand), then there<br>
&gt;     aren&#39;t enough risky cases left to warrant adding this level of complexity to the<br>
&gt;     protocol system.<br>
&gt;<br>
&gt;<br>
&gt;         As others point out, there&#39;s a temptation here to write things like<br>
&gt;         &quot;transient(Equatable)&quot; so as to control the synthesis of implementations on a<br>
&gt;         per-protocol basis. By that point, you&#39;ve invented a whole new syntax for<br>
&gt;         implementing protocol requirements. (Ah, you might say, but it&#39;s hard to<br>
&gt;         write a good hashValue implementation: sure, but that&#39;s adequately solved by<br>
&gt;         a library-supplied combineHashes() function.)<br>
&gt;<br>
&gt;<br>
&gt;     I totally agree with this. A design that would try to annotate &quot;transient&quot; with a<br>
&gt;     protocol or list of protocols is missing the point of the semantics that<br>
&gt;     &quot;transient&quot; is supposed to provide. It&#39;s not a series of switches to that can be<br>
&gt;     flipped on and off for arbitrary protocolsБ─■it&#39;s a semantic tag that assigns<br>
&gt;     additional meaning to properties and certain protocols (such as Equatable,<br>
&gt;     Hashable, and Codable, but possibly others that haven&#39;t been designed yet) would<br>
&gt;     have protocol-specific behavior for those properties.<br>
&gt;<br>
&gt;     To better explain what I&#39;ve been poking at, I&#39;m kind of extrapolating this out to<br>
&gt;     a possible future where it may be possible to more generally (1) define custom<br>
&gt;     @attributes in Swift, like Java annotations, and then (2) use some<br>
&gt;     metaprogramming constructs to generate introspective default implementations for<br>
&gt;     a protocol at compile-time just as the compiler does &quot;magically&quot; now, and the<br>
&gt;     generator would be able to query attributes that are defined by the same library<br>
&gt;     author as the protocol and handle them accordingly.<br>
&gt;<br>
&gt;     In a world where that&#39;s possible, I think it&#39;s less helpful to think in terms of<br>
&gt;     &quot;I need to distinguish between conforming to X and getting a synthesized<br>
&gt;     implementation and conforming to X and avoiding the synthesized implementation<br>
&gt;     because the default might be risky&quot;, but instead to think in terms of &quot;How can I<br>
&gt;     provide enough semantic information about my types to remove the risk?&quot;<br>
&gt;<br>
&gt;     In other words, the switches we offer developers to flip shouldn&#39;t be about<br>
&gt;     turning on/off entire features, but about giving the compiler enough information<br>
&gt;     to make it smart enough that we never need to turn it off in the first place. As<br>
&gt;     I alluded to before, if I have 10 properties in a type and only 1 of those needs<br>
&gt;     to be ignored in ==/hashValue/whatever, writing &quot;Equatable&quot; instead of &quot;derives<br>
&gt;     Equatable&quot; isn&#39;t all that helpful. Yes, it spits out an error message where there<br>
&gt;     wouldn&#39;t have been one, but it doesn&#39;t reduce any of the burden of having to<br>
&gt;     provide the appropriate manual implementation.<br>
&gt;<br>
&gt;     But all that stuff about custom attributes and metaprogramming introspection is a<br>
&gt;     big topic of it&#39;s own that isn&#39;t going to be solved in Swift 5, so this is a bit<br>
&gt;     of a digression. :)<br>
&gt;<br>
&gt;<br>
&gt; That said, we could have enums EquatingKeys and HashingKeys, a la CodingKeys... That<br>
&gt; may not be a huge leap to propose and implement.<br>
<br>
Actually, not taking into account a question of explicit marker for auto-generated<br>
methods, this is IMO a great point.<br>
<br>
Codable, which can auto-generate methods, *had* these CodingKeys from the moment of<br>
birth. Currently, we have a proposal for auto-generating of methods for<br>
Equatable/Hashable. Why we don&#39;t have a EquatingKeys/HashingKeys option for them in<br>
symmetry with Codable? Why Codable already has a method to exclude fields, but for<br>
Equatable/Hashable we are discussing some future esoteric &#39;@transient&#39; modifier(which<br>
should describe the behaviour and destination of the property in details for compiler<br>
and conformed protocols so all will &quot;just work&quot;) ?<br>
How this future &#39;@transient&#39; will live together with current CodingKeys ?<br>
<br>
IMO the right solution will be:<br>
1. introduce &#39;deriving&#39;-like keyword to explicitly express that you request an<br>
auto-synthesize of protocol requirements<br>
2. introduce EquatingKeys/HashingKeys to be able to say which properties should be<br>
included in generated requirements<br>
3. Think what kind of &#39;@transient&#39; marker could be introduced in future to replace<br>
the using of CodingKeys/EquatingKeys/HashingKeys.<br></blockquote><div><br></div><div>I don&#39;t agree with Xiaodi here that a hypothetical EquatableKey/HashableKey would be the same thing as CodingKey.</div><div><br></div><div>CodingKey embeds other semantic information, like the string or integer key to use when encoding/decoding a value in a container. The cases of a CodingKey enum are also actual values that are passed around to other encoder/decoder methods—they&#39;re not *just* there for the synthesized code.</div><div><br></div><div>Equatable/HashableKeys wouldn&#39;t be that. The cases would never be used anywhere else, passed anywhere, or returned from anything. It would just be a list of cases that match property names, which doesn&#39;t really feel like the right model here. Simply put, if the values aren&#39;t useful *as values*, they shouldn&#39;t be modeled as values.</div><div><br></div><div>I also don&#39;t see how &quot;transient&quot; would ever replace CodingKeys. Instead, it would augment it. Right now, the compiler autogenerates CodingKeys if you don&#39;t provide one. What &quot;transient&quot; would do is affect *what* the compiler generates for you there; likewise with Equatable and Hashable. They&#39;re not identical concepts.</div><div> <br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Vladimir.<br>
<br>
&gt;<br>
&gt;             -Thorsten<br>
&gt;<br>
&gt;             Am 12.09.2017 um 16:38 schrieb Tony Allevato via swift-evolution<br>
&gt;             &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt;:<br>
&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;             On Mon, Sep 11, 2017 at 10:05 PM Gwendal Rouц╘ &lt;<a href="mailto:gwendal.roue@gmail.com" target="_blank">gwendal.roue@gmail.com</a><br>
&gt;&gt;             &lt;mailto:<a href="mailto:gwendal.roue@gmail.com" target="_blank">gwendal.roue@gmail.com</a>&gt;&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;                     This doesn&#39;t align with how Swift views the role of<br>
&gt;&gt;&gt;&gt;                     protocols, though. One of the criteria that the core team has<br>
&gt;&gt;&gt;&gt;                     said they look for in a protocol is &quot;what generic algorithms<br>
&gt;&gt;&gt;&gt;                     would be written using this protocol?&quot; AutoSynthesize doesn&#39;t<br>
&gt;&gt;&gt;&gt;                     satisfy thatБ─■there are no generic algorithms that you would<br>
&gt;&gt;&gt;&gt;                     write with AutoEquatable that differ from what you would<br>
&gt;&gt;&gt;&gt;                     write with Equatable.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;                     And so everybody has to swallow implicit and non-avoidable<br>
&gt;&gt;&gt;                     code synthesis and shut up?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;                 That&#39;s not what I said. I simply pointed out one of the barriers<br>
&gt;&gt;&gt;                 to getting a new protocol added to the language.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;                 Code synthesis is explicitly opt-in and quite avoidableБ─■you either<br>
&gt;&gt;&gt;                 don&#39;t conform to the protocol, or you conform to the protocol and<br>
&gt;&gt;&gt;                 provide your own implementation. What folks are differing on is<br>
&gt;&gt;&gt;                 whether there should have to be *two* explicit switches that you<br>
&gt;&gt;&gt;                 flip instead of one.<br>
&gt;&gt;<br>
&gt;&gt;                 No. One does not add a protocol conformance by whim. One adds a<br>
&gt;&gt;                 protocol conformance by need. So the conformance to the protocol is<br>
&gt;&gt;                 a *given* in our analysis of the consequence of code synthesis. You<br>
&gt;&gt;                 can not say &quot;just don&#39;t adopt it&quot;.<br>
&gt;&gt;<br>
&gt;&gt;                 As soon as I type the protocol name, I get synthesis. That&#39;s the<br>
&gt;&gt;                 reason why the synthesized code is implicit. The synthesis is<br>
&gt;&gt;                 explicitly written in the protocol documentation, if you want. But<br>
&gt;&gt;                 not in the programmer&#39;s code.<br>
&gt;&gt;<br>
&gt;&gt;                 I did use &quot;non-avoidable&quot; badly, you&#39;re right: one can avoid it, by<br>
&gt;&gt;                 providing its custom implementation.<br>
&gt;&gt;<br>
&gt;&gt;                 So the code synthesis out of a mere protocol adoption *is* implicit.<br>
&gt;&gt;<br>
&gt;&gt;&gt;                 Let&#39;s imagine a pie. The whole pie is the set of all Swift types.<br>
&gt;&gt;&gt;                 Some slice of that pie is the subset of those types that satisfy<br>
&gt;&gt;&gt;                 the conditions that allow one of our protocols to be synthesized.<br>
&gt;&gt;&gt;                 Now that slice of pie can be sliced again, into the subset of<br>
&gt;&gt;&gt;                 types where (1) the synthesized implementation is correct both in<br>
&gt;&gt;&gt;                 terms of strict value and of business logic, and (2) the subset<br>
&gt;&gt;&gt;                 where it is correct in terms of strict value but is not the right<br>
&gt;&gt;&gt;                 business logic because of something like transient data.<br>
&gt;&gt;<br>
&gt;&gt;                 Yes.<br>
&gt;&gt;<br>
&gt;&gt;&gt;                 What we have to consider is, how large is slice (2) relative to<br>
&gt;&gt;&gt;                 the whole pie, *and* what is the likelihood that developers are<br>
&gt;&gt;&gt;                 going to mistakenly conform to the protocol without providing<br>
&gt;&gt;&gt;                 their own implementation, *and* is the added complexity worth<br>
&gt;&gt;&gt;                 protecting against this case?<br>
&gt;&gt;<br>
&gt;&gt;                 That&#39;s quite a difficult job: do you think you can evaluate this<br>
&gt;&gt;                 likelihood?<br>
&gt;&gt;<br>
&gt;&gt;                 Explicit synthesis has big advantage: it avoids this question entirely.<br>
&gt;&gt;<br>
&gt;&gt;                 Remember that the main problem with slide (2) is that developers<br>
&gt;&gt;                 can not *learn* to avoid it.<br>
&gt;&gt;<br>
&gt;&gt;                 For each type is slide (2) there is a probability that it comes<br>
&gt;&gt;                 into existence with a forgotten explicit protocol adoption. And<br>
&gt;&gt;                 this probability will not go down as people learn Swift and<br>
&gt;&gt;                 discover the existence of slide (2). Why? because this probability<br>
&gt;&gt;                 is driven by unavoidable human behaviors:<br>
&gt;&gt;                 - developer doesn&#39;t see the problem (a programmer mistake)<br>
&gt;&gt;                 - the developper plans to add explicit conformance later and<br>
&gt;&gt;                 happens to forget (carelessness)<br>
&gt;&gt;                 - a developper extends an existing type with a transient property,<br>
&gt;&gt;                 and doesn&#39;t add the explicit protocol conformance that has become<br>
&gt;&gt;                 required.<br>
&gt;&gt;<br>
&gt;&gt;                 Case 2 and 3 bite even experienced developers. And they can&#39;t be<br>
&gt;&gt;                 improved by learning.<br>
&gt;&gt;<br>
&gt;&gt;                 Looks like the problem is better defined as an ergonomics issue, now.<br>
&gt;&gt;<br>
&gt;&gt;&gt;                 If someone can show me something that points to accidental<br>
&gt;&gt;&gt;                 synthesized implementations being a significant barrier to smooth<br>
&gt;&gt;&gt;                 development in Swift, I&#39;m more than happy to consider that<br>
&gt;&gt;&gt;                 evidence. But right now, this all seems hypothetical (&quot;I&#39;m worried<br>
&gt;&gt;&gt;                 that...&quot;) and what&#39;s being proposed is adding complexity to the<br>
&gt;&gt;&gt;                 language (an entirely new axis of protocol conformance) that would<br>
&gt;&gt;&gt;                 (1) solve a problem that may not exist to any great degree, and<br>
&gt;&gt;&gt;                 (2) does not address the fact that if that problem does indeed<br>
&gt;&gt;&gt;                 exist, then the same problem just as likely exists with certain<br>
&gt;&gt;&gt;                 non-synthesized default implementations.<br>
&gt;&gt;<br>
&gt;&gt;                 There is this sample code by Thorsten Seitz with a cached property<br>
&gt;&gt;                 which is quite simple and clear :<br>
&gt;&gt;                 <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html" rel="noreferrer" target="_blank">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html</a><br>
&gt;&gt;<br>
&gt;&gt;                 This is the sample code that had me enter the &quot;worried&quot; camp.&#39;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;             I really like Thorsten&#39;s example, because it actually proves that<br>
&gt;&gt;             requiring explicit derivation is NOT the correct approach here. (Let&#39;s<br>
&gt;&gt;             set aside the fact that Optionals prevent synthesis because we don&#39;t<br>
&gt;&gt;             have conditional conformances yet, and assume that we&#39;ve gotten that<br>
&gt;&gt;             feature as well for the sake of argument.)<br>
&gt;&gt;<br>
&gt;&gt;             Let&#39;s look at two scenarios:<br>
&gt;&gt;<br>
&gt;&gt;             1) Imagine I have a value type with a number of simple Equatable<br>
&gt;&gt;             properties. In a world where synthesis is explicit, I tell that value<br>
&gt;&gt;             type to &quot;derive Equatable&quot;. Everything is fine. Later, I decide to add<br>
&gt;&gt;             some cache property like in Thorsten&#39;s example, and that property just<br>
&gt;&gt;             happens to also be Equatable. After doing so, the correct thing to do<br>
&gt;&gt;             would be to remove the &quot;derive&quot; part and provide my custom<br>
&gt;&gt;             implementation. But if I forget to do that, the synthesized operator<br>
&gt;&gt;             still exists and applies to that type. If you&#39;re arguing that &quot;derive<br>
&gt;&gt;             Equatable&quot; is better because its explicitness prevents errors, you must<br>
&gt;&gt;             also accept that there are possibly just as many cases where that<br>
&gt;&gt;             explicitness does *not* prevent errors.<br>
&gt;&gt;<br>
&gt;&gt;             2) Imagine I have a value type with 10 Equatable properties and one<br>
&gt;&gt;             caching property that also happens to be Equatable. The solution being<br>
&gt;&gt;             proposed here says that I&#39;m better off with explicit synthesis because<br>
&gt;&gt;             if I conform that type to Equatable without &quot;derive&quot;, I get an error,<br>
&gt;&gt;             and then I can provide my own custom implementation. But I have to<br>
&gt;&gt;             provide that custom implementation *anyway* to ignore the caching<br>
&gt;&gt;             property even if we don&#39;t make synthesis explicit. Making it explicit<br>
&gt;&gt;             hasn&#39;t saved me any workБ─■it&#39;s only given me a compiler error for a<br>
&gt;&gt;             problem that I already knew I needed to resolve. If we tack on Hashable<br>
&gt;&gt;             and Codable to that type, then I still have to write a significant<br>
&gt;&gt;             amount of boilerplate for those custom operations. Furthermore, if<br>
&gt;&gt;             synthesis is explicit, I have *more* work because I have to declare it<br>
&gt;&gt;             explicitly even for types where the problem above does not occur.<br>
&gt;&gt;<br>
&gt;&gt;             So, making derivation explicit is simply a non-useful dodge that<br>
&gt;&gt;             doesn&#39;t solve the underlying problem, which is this: Swift&#39;s type<br>
&gt;&gt;             system currently does not distinguish between Equatable properties that<br>
&gt;&gt;             *do* contribute to the &quot;value&quot; of their containing instance vs.<br>
&gt;&gt;             Equatable properties that *do not* contribute to the &quot;value&quot; of their<br>
&gt;&gt;             containing instance. It&#39;s the difference between behavior based on a<br>
&gt;&gt;             type and additional business logic implemented on top of those types.<br>
&gt;&gt;<br>
&gt;&gt;             So, what I&#39;m trying to encourage people to see is this: saying &quot;there<br>
&gt;&gt;             are some cases where synthesis is risky because it&#39;s incompatible with<br>
&gt;&gt;             certain semantics, so let&#39;s make it explicit everywhere&quot; is trying to<br>
&gt;&gt;             fix the wrong problem. What we should be looking at is *&quot;how do we give<br>
&gt;&gt;             Swift the additional semantic information it needs to make the<br>
&gt;&gt;             appropriate decision about what to synthesize?&quot;*<br>
&gt;&gt;<br>
&gt;&gt;             That&#39;s where concepts like &quot;transient&quot; come in. If I have an<br>
&gt;&gt;             Equatable/Hashable/Codable type with 10 properties and one cache<br>
&gt;&gt;             property, I *still* want the synthesis for those first 10 properties. I<br>
&gt;&gt;             don&#39;t want the presence of *one* property to force me to write all of<br>
&gt;&gt;             that boilerplate myself. I just want to tell the compiler which<br>
&gt;&gt;             properties to ignore.<br>
&gt;&gt;<br>
&gt;&gt;             Imagine you&#39;re a stranger reading the code to such a type for the first<br>
&gt;&gt;             time. Which would be easier for you to quickly understand? The version<br>
&gt;&gt;             with custom implementations of ==, hashValue, init(from:), and<br>
&gt;&gt;             encode(to:) all covering 10 or more properties that you have to read<br>
&gt;&gt;             through to figure out what&#39;s being ignored (and make sure that the<br>
&gt;&gt;             author has done so correctly), or the version that conforms to those<br>
&gt;&gt;             protocols, does not contain a custom implementation, and has each<br>
&gt;&gt;             transient property clearly marked? The latter is more concise and<br>
&gt;&gt;             &quot;transient&quot; carries semantic weight that gets buried in a handwritten<br>
&gt;&gt;             implementation.<br>
&gt;&gt;<br>
&gt;&gt;             Here&#39;s a fun exerciseБ─■you can actually write something like &quot;transient&quot;<br>
&gt;&gt;             without any additional language support today:<br>
&gt;&gt;             <a href="https://gist.github.com/allevato/e1aab2b7b2ced72431c3cf4de71d306d" rel="noreferrer" target="_blank">https://gist.github.com/allevato/e1aab2b7b2ced72431c3cf4de71d306d</a>. A<br>
&gt;&gt;             big drawback to this Transient type is that it&#39;s not as easy to use as<br>
&gt;&gt;             an Optional because of the additional sugar that Swift provides for the<br>
&gt;&gt;             latter, but one could expand it with some helper properties and methods<br>
&gt;&gt;             to sugar it up the best that the language will allow today.<br>
&gt;&gt;<br>
&gt;&gt;             I would wager that this concept, either as a wrapper type or as a<br>
&gt;&gt;             built-in property attribute, would solve a significant majority of<br>
&gt;&gt;             cases where synthesis is viewed to be &quot;risky&quot;. If we accept that<br>
&gt;&gt;             premise, then we can back to our slice of pie and all we&#39;re left with<br>
&gt;&gt;             in terms of &quot;risky&quot; types are &quot;types that contain properties that<br>
&gt;&gt;             conform to a certain protocol but are not really transient but also<br>
&gt;&gt;             shouldn&#39;t be included verbatim in synthesized operations&quot;. I&#39;m<br>
&gt;&gt;             struggling to imagine a type that fits that description, so if they do<br>
&gt;&gt;             exist, it&#39;s doubtful that they&#39;re a common enough problem to warrant<br>
&gt;&gt;             introducing more complexity into the protocol conformance system.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;                 Gwendal<br>
&gt;&gt;<br>
&gt;&gt;             _______________________________________________<br>
&gt;&gt;             swift-evolution mailing list<br>
&gt;&gt;             <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;<br>
&gt;&gt;             <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt;             _______________________________________________<br>
&gt;             swift-evolution mailing list<br>
&gt;             <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;<br>
&gt;             <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<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>