<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On May 20, 2016, at 8:53 PM, Brent Royal-Gordon &lt;<a href="mailto:brent@architechies.com" class="">brent@architechies.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><blockquote type="cite" class="">You can implement reference types with value semantics and value types with reference semantics.<br class=""></blockquote><br class=""><blockquote type="cite" class="">Immutable reference types actually *can* provide valid value semantics (at least as long as as they can provide their own implementation of `==` which I believe Dave A is arguing against).<br class=""></blockquote><br class="">Not in the sense I mean—that is, not if the protocol has members which require you to mutate self.<br class=""></div></div></blockquote><div><br class=""></div>Yes, it goes without saying that an <i class="">immutable</i> reference type cannot have a mutating member.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">If a reference type is immutable, you can treat it like a value type. But then it can't correctly conform to a protocol (like `RangeReplaceableCollection`) with mutating members, because it is *immutable*. It would have to take `self` as an `inout` parameter and replace `self` with a copy, but methods on classes cannot take `self` as an inout parameter. It's stuck.<br class=""></div></div></blockquote><div><br class=""></div><div>It’s not just for that reason alone. &nbsp;An immutable type would not be able to support operations that mutate, regardless of the need to take `self` as an `inout`parameter. &nbsp;For example, if there were `NSImmutableArray` (`NSArray` does not guarantee immutability, it just doesn’t expose mutating operations) it would not be able to conform to `RangeReplaceableCollection` most importantly because you could not do things like `replaceSubrange`.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">In other words, there are three sensible types of protocols:<br class=""><br class="">1. Protocols that do not require any self-mutating members, and do not assume either value or reference semantics.</div></div></blockquote><blockquote type="cite" class=""><div class=""><div class="">2. Protocols that require self-mutating members, and assume value semantics.<br class="">3. Protocols that require self-mutating members, and assume reference semantics.<br class=""></div></div></blockquote><div><br class=""></div><div>It is also sensible to have a protocol that requires value semantics even if it does not have mutating operations. &nbsp;There are times when you want a guarantee that you will not observe mutations made by others.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">However, what Swift actually supports is:&nbsp;<br class=""><br class="">1. Protocols that do not require any self-mutating members, and do not assume either value or reference semantics.<br class="">2. Protocols that require self-mutating members, and can be implemented by either classes or structs/enums.<br class="">3. Protocols that require self-mutating members, and must be implemented by classes.<br class=""><br class="">The mismatch in #2 (between assuming value semantics and allowing classes to conform) is one source of mischief: the compiler does nothing to help you realize that you cannot possibly correctly conform a class to the protocol. Requiring you to use a struct or an enum is not *sufficient* to ensure you'll provide value semantics, but it is *necessary* in the face of self-mutation.<br class=""><br class="">The mismatch in #3 (between assuming reference semantics and requiring a class) is another, separate source of mischief: your particular value type happens to provide reference semantics even in the face of self-mutation, but it can't conform to a class-constrained protocol. This *is* a problem, but I consider it less important because you can always wrap your value type in a class to convince the compiler you know what you're doing.<br class=""><br class="">In #2, the compiler is not being cautious enough; in #3, it's being too cautious. You can work around #3, but there's no fix for the recklessness in #2.<br class=""><br class=""><blockquote type="cite" class="">Until the compiler can verify value semantics I am not sure there is a benefit to `any&lt;value&gt;`. &nbsp;The semantic distinction is what is important. &nbsp;There has been discussion about strengthening the “value type == value semantics” and “reference type == reference semantics” relations but that hasn’t yet moved beyond talk.<br class=""></blockquote><br class="">Don't let the perfect be the enemy of the good. If the algorithm can't possibly work properly with a type that has reference semantics, then rejecting class types is a good first step, even if it doesn't reject every type with reference semantics.<br class=""></div></div></blockquote><div><br class=""></div><div>Fair enough. &nbsp;But in that case I think we want something that does exactly that: rejects classes, rather than indicating value semantics. &nbsp;We need to do this in a way that doesn’t lead to a situation where we used the word `value` to mean “value type”, and later we have the capability to very value semantics and really wish `value` could mean value semantics but that would be a breaking change we aren’t willing to make.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">(I've read the arguments about pure vs. non-pure value type conformances and I'm not convinced. It is always possible to nominally "conform" to a protocol in a way that actually undermines its guarantees; for example, you could implement `RangeReplaceableCollection.remove(at:)` as a no-op. The compiler cannot reject all invalid conformances; it can only reject ones which it can trivially show are invalid, because for instance they do not even attempt to provide a required method. Similarly, the compiler may not be able to prove you are providing value semantics, but it *can* reject conformances of reference types to a protocol requiring value semantics, since those cannot possibly be valid conformances.<br class=""></blockquote><br class="">There is a big difference between semantics that the compiler *could* but *does not yet* verify and semantics that simply cannot be verified.<br class=""></blockquote><br class="">And there's also a difference between research projects leading to large-scale changes to foundational language features and incremental fixes. `value` or `!class` or whatever we call it is something we could add to the language without any big redesigns or deep ponderings about the meaning of `==`. It would not be 100%, but it would filter out a fair bit of obviously incorrect code.<br class=""></div></div></blockquote><div><br class=""></div><div>I don’t think this is a research project. &nbsp;IIRC the core team has already talked positively about supporting pure functions eventually, for example. &nbsp;There is a lot of overlap in the work to verify that a function is pure and the work involved in verifying value semantics.</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><blockquote type="cite" class="">Incidentally, it is not possible to satisfy static property/method requirements with cases, but it probably should be:<br class=""></blockquote><br class="">But that is mostly tangential to this discussion.<br class=""></blockquote><br class="">Yes, that is very tangential. Honestly, it's kind of a tangent to a tangent.<br class=""></div></div></blockquote><div><br class=""></div><div>I don’t think it’s that far off. &nbsp;It’s related to Any&lt;enum&gt; because protocols with case requirements could only be implemented by an enum. &nbsp;But that’s a discussion for another day (and is probably not the best way to achieve the goal behind that request anyway).</div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><br class="">-- <br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class=""></div></div></blockquote></div><br class=""></body></html>