<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="">Hi Karl and Haravikk,<div class=""><br class=""></div><div class="">Thank you for your replies. </div><div class=""><br class=""></div><div class="">I was <i class="">assuming</i> that the cases I represented are not always optimized for several reasons:</div><div class=""><ol class="MailOutline"><li class="">Swift’s book only talks about optimization in the context of arrays, strings and dictionaries. Not in the context of structs in general:<br class="">“The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.”<br class="">Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2.2).” iBooks. <a href="https://itun.es/nl/jEUH0.l" class="">https://itun.es/nl/jEUH0.l</a></li><li class="">In <a href="https://github.com/apple/swift/tree/eb27bb65a7c17bd9b4255baee5c4e4f9c214bde6/stdlib/public/core" class="">https://github.com/apple/swift/tree/eb27bb65a7c17bd9b4255baee5c4e4f9c214bde6/stdlib/public/core</a> I see </li><li class=""><table data-tab-size="8" style="box-sizing: border-box; border-spacing: 0px; border-collapse: collapse; tab-size: 8; color: rgb(51, 51, 51); font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px;" class="js-file-line-container highlight tab-size"><tbody style="box-sizing: border-box;" class=""><tr style="box-sizing: border-box;" class=""><td id="LC1268" style="box-sizing: border-box; padding: 0px 10px; position: relative; vertical-align: top; overflow: visible; word-wrap: normal;" class="js-file-line blob-code-inner blob-code"><span style="line-height: 20px; white-space: pre;" class=""><span style="font-size: 12px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(167, 29, 93);" class="pl-k">public</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="font-size: 12px;" class=""> </font><span style="font-size: 12px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(167, 29, 93);" class="pl-k">mutating</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="font-size: 12px;" class=""> </font><span style="font-size: 12px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(167, 29, 93);" class="pl-k">func</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="font-size: 12px;" class=""> </font><span style="font-size: 12px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(121, 93, 163);" class="pl-en">append</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="font-size: 12px;" class="">(</font><span style="font-size: 12px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(121, 93, 163);" class="pl-en">_</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="font-size: 12px;" class=""> </font><span style="font-size: 12px; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box;" class="pl-smi">newElement</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="font-size: 12px;" class="">: Element)</font><font style="font-size: 12px;" face="Helvetica" class=""> , line 1268,</font><span style="font-size: 12px; color: rgb(0, 0, 0); line-height: normal; white-space: normal;" class=""><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" class=""><br class=""></font></span><span style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; line-height: normal; white-space: normal;" class="">using </span><span style="font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; background-color: rgb(255, 255, 255);" class="">_makeUniqueAndReserveCapacityIfNotUnique()</span> </span><font color="#000000" face="Helvetica" class=""><span style="font-size: 12px;" class="">at line 1269, leading me to <i class="">suspect</i> that to have COW, you have to do additional work.</span></font></td></tr></tbody></table></li><li class="">Doing some manual tests some time ago, <span style="color: rgb(61, 29, 129); font-family: Menlo; font-size: 11px;" class="">isUniquelyReferenced</span> seemed to return false in a case like append_one as <a href="https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-inplace-mutation-instead-of-object-reassignment" class="">https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-inplace-mutation-instead-of-object-reassignment</a> mentioned by Karl, meaning that it indeed leads to unnecessary copying.</li></ol><div class=""><br class=""></div><div class="">In any case, <a href="https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-inplace-mutation-instead-of-object-reassignment" class="">https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-inplace-mutation-instead-of-object-reassignment</a> does mention that: “Sometimes COW can introduce additional unexpected copies if the user is not careful.” I would argue that what we need is not only COW, but Copy On Write When Necessary, COWWN. In COWWN copies are only made when writing to the shared reference if it is not unique <b class="">and</b> the shared reference’s old state is still referred to in next statements. So not only is the current reference count taken into account, but also whether the old state is needed afterwards. This is both runtime as well as compile-time data.</div><div class=""><br class=""></div><div class="">So my questions would be:</div><div class=""><ol class="MailOutline"><li class="">Why does Swift sometimes do additional unnecessary copying, as implied by <a href="https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-inplace-mutation-instead-of-object-reassignment" class="">https://github.com/apple/swift/blob/master/docs/OptimizationTips.rst#advice-use-inplace-mutation-instead-of-object-reassignment</a> in the case of append_one? Is this a problem that cannot be solved? (In C++ you would solve this example using a=a.append_one(std::move(a)). But I would think that since Swift does not have to deal with pointers and manual memory management, it can automatically detect such cases unlike C++?)</li><li class="">If/once structs are COWWN, can Swift introduce immutable functions for the standard library, such as<font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="color: rgb(51, 51, 51); line-height: 20px; white-space: pre;" class=""> </font><span class="pl-k" style="line-height: 20px; white-space: pre; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(167, 29, 93);">func</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="color: rgb(51, 51, 51); line-height: 20px; white-space: pre;" class=""> </font><span class="pl-en" style="line-height: 20px; white-space: pre; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(121, 93, 163);">appended</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="color: rgb(51, 51, 51); line-height: 20px; white-space: pre;" class="">(</font><span class="pl-en" style="line-height: 20px; white-space: pre; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box; color: rgb(121, 93, 163);">_</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="color: rgb(51, 51, 51); line-height: 20px; white-space: pre;" class=""> </font><span class="pl-smi" style="color: rgb(51, 51, 51); line-height: 20px; white-space: pre; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; box-sizing: border-box;">newElement</span><font face="Consolas, Liberation Mono, Menlo, Courier, monospace" style="color: rgb(51, 51, 51); line-height: 20px; white-space: pre;" class="">: Element) -> Array<Element>?</font></li></ol><div class=""><div class=""><br class=""></div><div class="">Best regards,</div></div></div><div class="">Bram.</div><div class=""><br class=""></div></div><div class=""><div><blockquote type="cite" class=""><div class="">On 30 jul. 2016, at 12:46, Haravikk <<a href="mailto:swift-evolution@haravikk.me" class="">swift-evolution@haravikk.me</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""></div><div class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""></div></div></div></div><blockquote type="cite" class=""><div class="">On 29 Jul 2016, at 17:42, Bram Beernink via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><br class="Apple-interchange-newline"><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi all,<div class=""><br class=""></div><div class="">Would it be possible to improve value and move semantics (performance) in Swift? Consider this possible Swift code in a future release of Swift:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);" class="">let</span> array1 : [<span style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);" class="">String</span>] = [<span style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);" class="">"Val1"</span>, <span style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);" class="">"Val2"</span>]</div><div style="margin: 0px;" class=""><span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">let</span><span style="font-family: Menlo; font-size: 11px;" class=""> array2 = </span><span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">array1</span><span style="font-family: Menlo; font-size: 11px;" class="">.appended(</span><font color="#d12f1b" face="Menlo" class=""><span style="font-size: 11px;" class="">“Val3”</span></font><font face="Menlo" class=""><span style="font-size: 11px;" class="">) </span></font><font color="#008400" face="Menlo" class=""><span style="font-size: 11px;" class="">// Copy of array1 with “Val3” appended. array1 is left untouched. Nothing special yet.</span></font></div><div style="margin: 0px;" class=""><span style="font-family: Menlo; font-size: 11px; color: rgb(187, 44, 162);" class="">var</span><font face="Menlo" class=""><span style="font-size: 11px;" class=""> array3</span></font><span style="font-family: Menlo; font-size: 11px;" class=""> : [</span><span style="font-family: Menlo; font-size: 11px; color: rgb(112, 61, 170);" class="">String</span><span style="font-family: Menlo; font-size: 11px;" class="">] </span><font face="Menlo" class=""><span style="font-size: 11px;" class="">= [</span></font><font color="#d12f1b" face="Menlo" class=""><span style="font-size: 11px;" class="">“Var1</span></font><font face="Menlo" class=""><font color="#d12f1b" class=""><span style="font-size: 11px;" class="">”</span></font><span style="font-size: 11px;" class="">]</span></font></div><div style="margin: 0px;" class=""><span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">array3</span><span style="font-family: Menlo; font-size: 11px;" class=""> = </span><span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">array3</span><span style="font-family: Menlo; font-size: 11px;" class="">.appended(</span><font color="#d12f1b" face="Menlo" class=""><span style="font-size: 11px;" class="">“Var2”</span></font><font face="Menlo" class=""><span style="font-size: 11px;" class="">) </span></font><font color="#008400" face="Menlo" class=""><span style="font-size: 11px;" class="">// <b class="">array3 can just be mutated to add “Var2”</b>, while maintaining value semantics. Swift can recognize that array3’s old state is not referenced anywhere in the future.</span></font></div><div style="margin: 0px; font-size: 11px; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);" class="">let</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> array4 = array2.appended(</span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);" class="">"Val4"</span><span style="font-variant-ligatures: no-common-ligatures;" class="">).appended(</span><span style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);" class="">"Val5"</span><span style="font-variant-ligatures: no-common-ligatures;" class="">) </span>// Copy of array2 with both "Val4" and "Val5" appended. In this case, “Val5” can also be appended by mutation.</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Well, for the array3 = array3.appended("Var2") example this could possibly be addressed by an attribute to indicate to the compiler that .appended() has a mutating variant, as this will allow it to issue a warning when the assignment is to the same variable, which would address that simple case (and provide more awareness of the mutating options and encourage developers to use them).</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="margin: 0px; font-size: 11px; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-family: Helvetica; font-size: 12px;" class="">This example illustrates improved value semantics with a string array. But it would be good if this can work with any struct. Maybe via something similar to </span><span style="color: rgb(61, 29, 129);" class="">isUniquelyReferenced? </span><span style="font-family: Helvetica; font-size: 12px;" class="">Or maybe you can even have a “smart” self in a non-mutating func in a struct:</span></div><div style="margin: 0px;" class=""><div class=""><div style="margin: 0px;" class=""><div style="font-family: Menlo; font-size: 11px; margin: 0px;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span> Array<T> {</div><div style="font-family: Menlo; font-size: 11px; margin: 0px;" class=""> <span style="color: rgb(187, 44, 162);" class="">func</span> appended(e : <span style="color: rgb(112, 61, 170);" class="">T</span>) -> <span style="color: rgb(79, 129, 135);" class="">Array</span><<span style="color: rgb(112, 61, 170);" class="">T</span>> { <span style="color: rgb(0, 132, 0);" class="">// No mutating keyword!</span></div><div style="margin: 0px;" class=""><font face="Menlo" class=""><span style="font-size: 11px;" class=""> </span></font><span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">self</span><font face="Menlo" class=""><span style="font-size: 11px;" class="">.append(e) </span></font><font color="#008400" face="Menlo" class=""><span style="font-size: 11px;" class="">// <b class="">self would either be mutated here if the current ref count of self is 1, and self is either a “rvalue” or self’s old state cannot possibly referenced anymore after this call. Otherwise, "self” would actually be a copy of self.</b></span></font></div><div style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px; margin: 0px;" class=""><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span>return<span style="font-variant-ligatures: no-common-ligatures;" class=""> </span>self</div><div style="font-family: Menlo; font-size: 11px; margin: 0px;" class=""> }</div><div style="font-family: Menlo; font-size: 11px; margin: 0px;" class="">}</div></div></div></div></div></blockquote></div><br class=""><div class="">I don't know about allowing mutation of self in non-mutating methods, that seems confusing; however, I'd be surprised if the compiler doesn't already detect variables that only exist to create a copy that is discarded.</div><div class=""><br class=""></div><div class="">The compiler should already be trying to inline very simple methods like the common copy -> mutate -> return style of non-mutating implementations, in which case it should be able to identify that a copy is being created only to overwrite the original anyway, so can be eliminated. Do you believe that this isn't currently being done?</div></div></div></blockquote></div><br class=""></div></body></html>