<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=""><div class=""></div><div class=""><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><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 class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">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 class="" style="margin: 0px; font-size: 11px; font-family: Menlo;"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span> array1 : [<span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(112, 61, 170);">String</span>] = [<span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Val1"</span>, <span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Val2"</span>]</div><div class="" style="margin: 0px;"><span class="" style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;">let</span><span class="" style="font-family: Menlo; font-size: 11px;"> array2 = </span><span class="" style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;">array1</span><span class="" style="font-family: Menlo; font-size: 11px;">.appended(</span><font color="#d12f1b" face="Menlo" class=""><span class="" style="font-size: 11px;">“Val3”</span></font><font face="Menlo" class=""><span class="" style="font-size: 11px;">) </span></font><font color="#008400" face="Menlo" class=""><span class="" style="font-size: 11px;">// Copy of array1 with “Val3” appended. array1 is left untouched. Nothing special yet.</span></font></div><div class="" style="margin: 0px;"><span class="" style="font-family: Menlo; font-size: 11px; color: rgb(187, 44, 162);">var</span><font face="Menlo" class=""><span class="" style="font-size: 11px;"> array3</span></font><span class="" style="font-family: Menlo; font-size: 11px;"> : [</span><span class="" style="font-family: Menlo; font-size: 11px; color: rgb(112, 61, 170);">String</span><span class="" style="font-family: Menlo; font-size: 11px;">] </span><font face="Menlo" class=""><span class="" style="font-size: 11px;">= [</span></font><font color="#d12f1b" face="Menlo" class=""><span class="" style="font-size: 11px;">“Var1</span></font><font face="Menlo" class=""><font color="#d12f1b" class=""><span class="" style="font-size: 11px;">”</span></font><span class="" style="font-size: 11px;">]</span></font></div><div class="" style="margin: 0px;"><span class="" style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;">array3</span><span class="" style="font-family: Menlo; font-size: 11px;"> = </span><span class="" style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;">array3</span><span class="" style="font-family: Menlo; font-size: 11px;">.appended(</span><font color="#d12f1b" face="Menlo" class=""><span class="" style="font-size: 11px;">“Var2”</span></font><font face="Menlo" class=""><span class="" style="font-size: 11px;">) </span></font><font color="#008400" face="Menlo" class=""><span class="" style="font-size: 11px;">// <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 class="" style="margin: 0px; font-size: 11px; font-family: Menlo; color: rgb(0, 132, 0);"><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(187, 44, 162);">let</span><span class="" style="font-variant-ligatures: no-common-ligatures;"> array4 = array2.appended(</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Val4"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">).appended(</span><span class="" style="font-variant-ligatures: no-common-ligatures; color: rgb(209, 47, 27);">"Val5"</span><span class="" style="font-variant-ligatures: no-common-ligatures;">) </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><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 class="" style="color: rgb(61, 29, 129);">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></body></html>