<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><span></span></div><div><div><br><br>Sent from my iPad</div><div><br>On Aug 19, 2017, at 3:29 PM, Michel Fortin &lt;<a href="mailto:michel.fortin@michelf.ca">michel.fortin@michelf.ca</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><br class=""><div><blockquote type="cite" class=""><div class="">Le 19 août 2017 à 11:38, Matthew Johnson &lt;<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: SourceSansPro-Regular; font-size: 15px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class=""></span></div><div style="font-family: SourceSansPro-Regular; font-size: 15px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class=""><br class=""><br class="">Sent from my iPad</div><div class=""><br class="">On Aug 19, 2017, at 8:16 AM, Michel Fortin via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">For instance, has Array&lt;UIView&gt; value semantics?<span class="Apple-converted-space">&nbsp;</span></div></div></div></blockquote><div class=""><br class=""></div><div class="">By the commonly accepted definition, Array&lt;UIView&gt; does not provide value semantics.</div></div></div></div></blockquote><div class=""><blockquote type="cite" class=""><br class=""></blockquote></div><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">You might be tempted to say that it does not because it contains class references, but in reality that depends on what you do with those UIViews.</div></div></div></blockquote><div class=""><br class=""></div><div class="">An aspect of the type (“does it have value semantics or not”) should not depend on the clients. &nbsp;By your definition, every type has value semantics if none of the mutating operations are called :-)</div></div></div></div></blockquote><br class=""><div class="">No, not mutating operations. Access to mutable memory shared by multiple "values" is what breaks value semantics. You can get into this situation using pointers, object references, or global variables. It's all the same thing in the end: shared memory that can mutate.</div><div class=""><br class=""></div><div class="">For demonstration's sake, here's a silly example of how you can give Array&lt;Int&gt; literally the same semantics as Array&lt;UIView&gt;:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// shared UIView instances in global memory</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>var instances: [UIView] = []</div><div class=""><br class=""></div></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>extension Array where Element == Int {</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// append a new integer to the array pointing to our UIView instance</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>func append(view: UIView) {</div><span class="Apple-tab-span" style="white-space: pre;">                        </span>self.append(instances.count)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                        </span>instances.append(newValue)<div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>}</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>// access views pointed to by the integers in the array</div></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>subscript(viewAt index: Int) -&gt; UIView {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                        </span>get {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                                </span>return instances[self[index]]</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                        </span>}</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                        </span>set {</div><span class="Apple-tab-span" style="white-space: pre;">                                </span>self[index] = instances.count<div class=""><span class="Apple-tab-span" style="white-space: pre;">                                </span>instances.append(newValue)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                        </span>}</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>}</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div><div class="">And now you need to worry about passing Array&lt;Int&gt; to other thread. ;-)</div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div class=""><div class=""><br class=""></div><div class="">It does not really matter whether the array contains pointers or wether it contains indices into a global table: in both cases access to the same mutable memory is accessible through multiple copies of an array, and this is what breaks value semantics.</div><div class=""><br class=""></div><div class="">Types cannot enforce value semantics. Its the functions you choose to call that matters. This is especially important to realize in a language with extensions where you can't restrict what functions gets attached to a type.</div></div></div></blockquote><div class=""><br class=""></div><div class="">This gets deeper into the territory of the conversation Dave A and I had a while ago. &nbsp;I think this conflates value semantics with pure functions, which I think is a mistake. &nbsp;</div><div class=""><br class=""></div><div class="">I agree that if you assume away reference counting a function that takes Array&lt;UIView&gt; but never dereferences the pointers can still be a pure function. &nbsp;However, I disagree that Array&lt;UIView&gt; has value semantics.</div></div></div></blockquote><div><blockquote type="cite" class=""><br class=""></blockquote></div></div><div><blockquote type="cite" class=""><div class=""><div style="font-family: SourceSansPro-Regular; font-size: 15px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">The relationship of value semantics to purity is that value semantics can be defined in terms of the purity of the "salient operations" of the type - those which represent the meaning of the value represented by the type. &nbsp;The purity of these operations is what gives the value independence from copies in terms of its meaning. &nbsp;If somebody chooses to add a new impure operation in an extension of a type with value semantics it does not mean that the type itself no longer has value semantics. &nbsp;The operation in the extension is not "salient".</div><div class=""><br class=""></div><div class="">This still begs the question: what operations are "salient"? &nbsp;I think everyone can agree that those used in the definition of equality absolutely must be included. &nbsp;If two values don't compare equal they clearly do not have the same meaning. &nbsp;<span style="background-color: rgba(255, 255, 255, 0);" class="">Thread safety is also usually implied for practical reasons as is the case in Chris's manifesto. &nbsp;These properties are generally considered necessary for value semantics.</span></div></div></div></blockquote><div><blockquote type="cite" class=""><br class=""></blockquote></div><blockquote type="cite" class=""><div class=""><div style="font-family: SourceSansPro-Regular; font-size: 15px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="">While these conditions are *necessary* for value semantics I do not believe they are *sufficient* for value semantics. &nbsp;Independence of the value is also required. &nbsp;When a reference type defines equality in terms of object identity copies of the reference are not truly independent. &nbsp;</div><div class=""><br class=""></div><div class="">This is especially true in a language like Swift where dereference is implicit. &nbsp;I argue that when equality is defined in terms of object identity copies of the reference are *not* independent. &nbsp;The meaning of the reference is inherently tied up with the resource it references. &nbsp;The resource has to be considered "salient" for the independence to be a useful property. &nbsp;On the other hand, if all you really care about is the identity and not the resource, ObjectIdentifier is available and does have value semantics. &nbsp;There is a very good reason this type exists.</div></div></div></blockquote><div><br class=""></div><div><div>The reason we're discussing value semantics here is because they are useful making concurrency safer. If we define the meaning of value semantics as "a type where a subset of the member functions (the important ones) can be used with concurrency" then that definition of value semantics lose quite a bit of its value for solving the problem at hand. It's too vague.</div><div><br class=""></div><div>I'm not actually that interested in the meaning of value semantics here. I'm debating the appropriateness of determining whether something can be done in another thread based on the type a function is attached to. Because that's what the ValueSemantical protocol wants to do. ValueSemantical, as a protocol, is whitelisting the whole type while in reality it should only vouch for a specific set of safe functions on that type.</div></div></div></div></blockquote><div><br></div><div>This is making some assumptions about the semantics of `ValueSemantical` and the compiler verification behind it, but I see what you're saying. &nbsp;It sounds to me like you're looking for a level of safety beyond what Chris is trying to tackle in his manifesto. &nbsp;My impression is that his goal is to make a pragmatic set of tradeoffs.</div><div><br></div><div>As an example to consider, we could write an extension method on `Int` that accesses some global state. &nbsp;It may use the value of the `Int` as an index into a global array. &nbsp;The existence and use of this method is completely orthogonal to whether or not it is safe to pass the `Int` as part of a message to an actor. &nbsp;The danger is in the use of the operation, not the source of the `Int`.</div><div><br></div><div>As I understand it, the intent of `ValueSemantical` is to avoid passing *access* to shared mutable state as part of a message to an actor. &nbsp;Passing an `Int` value does not give the actor any access it didn't already have. &nbsp;On the other hand, passing a `UIView` gives it access to shared mutable state it did not have before receiving the message.</div><div><br></div><div>Achieving the kind of safety you're looking for would require verification that an actor has exclusive access to all mutable state it uses (including state that is used by all functions it calls). &nbsp;This would be wonderful, but would also preclude a lot of very useful things, most importantly C-interop. &nbsp;Here is the relevant portion of Chris's manifesto regarding global mutable state and the tradeoffs he believes will be pragmatic and effective in practice:</div><div><br></div><div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; -webkit-text-size-adjust: 100%; background-color: rgb(255, 255, 255);">Since we're friends, I'll be straight with you: there are no great answers here. Swift and C already support global mutable state, so the best we can do is discourage the use of it. We cannot automatically detect a problem because actors need to be able to transitively use random code that isn't defined on the actor. For example:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; -webkit-text-size-adjust: 100%; background-color: rgb(255, 255, 255);"><pre style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; word-wrap: normal; padding: 16px; overflow: auto; background-color: rgb(246, 248, 250); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal;"><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">calculate</span>(<span class="pl-smi" style="box-sizing: border-box;"><span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">thing</span></span> : <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">Int</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">-&gt;</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">Int</span> { <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">...</span> }

actor Foo {
  actor <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">func</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">exampleOperation</span>() {
     <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">let</span> x <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">calculate</span>(<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">thing</span>: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 92, 197);">42</span>)
     <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">...</span>
  }
}</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; -webkit-text-size-adjust: 100%; background-color: rgb(255, 255, 255);">There is no practical way to know whether 'calculate' is thread-safe or not. The only solution is to scatter tons of annotations everywhere, including in headers for C code. I think that would be a non-starter.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; -webkit-text-size-adjust: 100%; background-color: rgb(255, 255, 255);">In practice, this isn't as bad as it sounds, because the most common operations that people use (e.g.&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">print</code>) are already internally synchronizing, largely because people are already writing multithreaded code. While it would be nice to magically solve this long standing problem with legacy systems, I think it is better to just completely ignore it and tell developers not to define or use global variables (global&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">let</code>s are safe).</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; -webkit-text-size-adjust: 100%; background-color: rgb(255, 255, 255);">All hope is not lost though: Perhaps we could consider deprecating global&nbsp;<code style="box-sizing: border-box; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.600000381469727px; padding: 0.2em 0px; margin: 0px; background-color: rgba(27, 31, 35, 0.0470588); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">var</code>s from Swift to further nudge people away from them. Also, any accesses to unsafe global global mutable state from an actor context can and should be warned about. Taking some steps like this should eliminate the most obvious bugs.</p></div><div><br></div><blockquote type="cite"><div><div><div><div><br class=""></div></div><blockquote type="cite" class=""><div class=""><div style="font-family: SourceSansPro-Regular; font-size: 15px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><span class=""></span></div></blockquote></div></div></blockquote></div><br class=""><div class="">
<div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-stroke-width: 0px;"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">--&nbsp;<br class="">Michel Fortin</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="text-align: -webkit-auto;" class=""><a href="https://michelf.ca" class="">https://michelf.ca</a></span></div></span></div></span></div></span></div></div></div></div>
</div>
<br class=""></div></blockquote></div></body></html>