<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="">I like the idea of Clonable, because it involves the least amount of boilerplate and I do certainly agree that not having to care about whether or not the object is a value type or a reference type is good for robust generic programming.<div class="">However, there are two problems that I see with it:</div><div class="">* The Clonable protocol is as pure magic as ExpressibleBy*Literal and Sequence, which may or may not be bad depending on the views and priorities of the core team.</div><div class="">* There is no way of avoiding a copy when one isn’t necessary. For instance, and object might be clonable, but that doesn’t mean that it should always be cloned.</div><div class=""><br class=""></div><div class="">The only good reason to use a value-type-semantical class is because if its deinit. And if you think about it, dragging an entire class with its virtual table is a gross overkill just for using ARC. Considering that classes and functions are the only reference types, things like Arrays and Dictionaries have to resort to gross hacks with using private classes and the ever so magical isKnowUniquelyReferenced function, which means that if you ever hope to allocate dynamic memory in a structure, you’re stuck with the Copy-On-Write semantic or a memory leak. The following magical protocol would solve all problems:</div><div class=""><br class=""></div><div class=""><font face="PT Mono" class=""><font color="#941751" class="">protocol</font> <font color="#008f00" class="">ReferenceSemantics</font> {</font></div><div class=""><span class="Apple-tab-span" style="white-space:pre"><font face="PT Mono" class="">        </font></span></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">func</font> retain()</font></div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">func</font> release()</font></div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class="">}</font></div><div class=""><br class=""></div><div class="">This alone would make a huge variety of use cases easy to write and fast to run, including every single collection type in Swift’s standard library (except maybe CollectionOfOne). So, dynamic allocations in Swift currently are only possible through the gross overhead of classes or manual memory management.</div><div class=""><br class=""></div><div class="">Currently, the only way that I know of to dynamically allocate a fixed-size value type inside another value type with full ARC support and without using classes is to abuse the fact that escaped locals in functions are ARC-ed:</div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class=""><font color="#941751" class="">public</font> <font color="#941751" class="">struct</font> <font color="#008f00" class="">Variable</font><<font color="#008f00" class="">Value</font>> {</font></div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">public</font> <font color="#941751" class="">init</font>(_ value: <font color="#008f00" class="">Value</font>) {</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#941751" class="">var</font> value = value</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#941751" class="">self</font>.getter = { <font color="#941751" class="">return</font> value }</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#941751" class="">self</font>.setter = { value = $0 }</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">public</font> <font color="#941751" class="">var</font> value: <font color="#008f00" class="">Value</font> {</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#941751" class="">get</font> {</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                        </span><font color="#941751" class="">return</font> <font color="#941751" class="">self</font>.getter()</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>}</font></div><div class=""><span class="Apple-tab-span" style="white-space:pre"><font face="PT Mono" class="">                </font></span></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span><font color="#941751" class="">nonmutating</font> <font color="#941751" class="">set</font> {</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span></font><span class="Apple-tab-span" style="font-family: 'PT Mono'; white-space: pre;">        </span><font face="PT Mono" class=""><font color="#941751" class="">self</font>.setter(newValue)</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>}</font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</font></div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">private</font> <font color="#941751" class="">let</font> getter: () -> <font color="#008f00" class="">Value</font></font></div><div class=""><span class="Apple-tab-span" style="white-space:pre"><font face="PT Mono" class="">        </font></span></div><div class=""><font face="PT Mono" class=""><span class="Apple-tab-span" style="white-space:pre">        </span><font color="#941751" class="">private</font> <font color="#941751" class="">let</font> setter: (Value) -> <font color="#008f00" class="">Void</font></font></div><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class="">}</font></div><div class=""><div class=""><font face="PT Mono" class=""><br class=""></font></div><div class=""><font face="PT Mono" class=""><font color="#941751" class="">let</font> v = <font color="#008f00" class="">Variable</font>(<font color="#0433ff" class="">“hello”</font>) <font color="#797979" class="">// a `let` constant</font></font></div><div class=""><font face="PT Mono" class="">assert(v.value == <font color="#0433ff" class="">“hello"</font>)</font></div><div class=""><font face="PT Mono" class="">v = <font color="#0433ff" class="">“world”</font> <font color="#797979" class="">// setter is nonmutating, so this is ok</font></font></div><div class=""><font face="PT Mono" class="">assert(v.value == <font color="#0433ff" class="">“world"</font>)</font></div><div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class="">On Jul 25, 2017, at 9:21 PM, Dave Abrahams via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">on Wed Jul 12 2017, Gor Gyolchanyan <</span><a href="mailto:swift-evolution@swift.org" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><span style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">> wrote:</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">Hello, swift community!<br class=""><br class="">Recently I’ve come across a dilemma regarding value-type semantics<br class="">when dealing with generic types. Consider a protocol that has a<br class="">mutating in-place function and a non-mutating returning variant of<br class="">that function:<br class=""><br class="">protocol Transmogrifier {<br class=""><br class=""> mutating func transmogrify()<br class=""><br class=""> func transmogrified() -> Self<br class=""><br class="">}<br class=""></blockquote><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">Ah, we're back in the territory of</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><a href="https://github.com/apple/swift/blob/master/docs/proposals/ValueSemantics.rst" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://github.com/apple/swift/blob/master/docs/proposals/ValueSemantics.rst</a><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><a href="https://github.com/apple/swift/blob/master/docs/proposals/Inplace.rst" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://github.com/apple/swift/blob/master/docs/proposals/Inplace.rst</a><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">(note, these are old; the syntax of the language has since evolved).</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">One of these methods has to have a default implementation in terms of the other.<br class=""><br class="">One way doing it is to implement the mutating version in terms of<br class="">non-mutating because it doesn’t depend on additional conditions to<br class="">work, since assigning to `self` causes a complete copy of the internal<br class="">state of the object regardless of whether it’s a value type or a<br class="">reference type. However, this approach has a big downside: in many<br class="">cases mutating functions mutate only part of the instance, which means<br class="">that an efficient implementation will have to implement the mutating<br class="">version and because of the way the default implementation works, the<br class="">non-mutating version would also need to be manually implemented, which<br class="">makes the default implementation useless in those cases.<br class=""><br class="">Implementing the non-mutating version in terms of mutating version<br class="">solves this problem nicely, allowing one to focus on mutating only the<br class="">necessary parts of the instance, while leaving the need to return a<br class="">separate instance to the default implementation, which would be<br class="">perfectly adequate in most cases.<br class=""></blockquote><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">Yes. There are cases where this approach ends up being less efficient,</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">e.g. when one of the arguments to the non-mutating form has</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">uniquely-referenced dynamically allocated storage that can be used by</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">the result, but handling these cases efficiently requires special</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">handling anyway, so the default implementation arrangement you're</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">suggesting makes sense.</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">This approach has its own problem that this pitch seeks to solve. The<br class="">problem becomes apparent when you consider this naive implementation:<br class=""><br class="">extension Transmogrifier {<br class=""><br class=""> public func transmogrified() -> Self {<br class=""> var result = self<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>result.transmogrify()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>return result<br class=""> }<br class=""><br class="">}<br class=""><br class="">The above implementation is only correct for value types, because<br class="">assignment is a deep copy.<span class="Apple-converted-space"> </span><br class=""></blockquote><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">Yes, I've wanted a way to constrain a generic so it only works on values</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">since before the release of Swift 1. There are at least two issues</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">that are still unsettled:<span class="Apple-converted-space"> </span></span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">1. what about value types that don't have value semantics?</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">2. what about immutable final class types (that do have value semantics)?</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">If the instance is of a reference type, the assignment will do nothing<br class="">and the call to the mutating version will apply to the original<br class="">object, violating the postcondition of the function (which states that<br class="">the function shall not modify the instance in any way).<br class=""><br class="">The most straight-forward way of solving this problem is to introduce<br class="">a new protocol for making sure the original instance is always copied:<br class=""><br class="">protocol CopyInitializable {<br class=""><br class=""> init(copying other: Self)<br class=""><br class="">}<br class=""><br class="">In which case the default implementation becomes fully correct:<br class=""><br class="">// The `CopyInitializable` conformance can also be moved to the protocol itself<br class="">// if the protocol conformance requires value-type semantics.<br class="">extension Transmogrifier where Self: CopyInitializable {<br class=""><br class=""> public func transmogrified() -> Self {<br class=""> var result = Self(copying: self)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>result.transmogrify()<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>return result<br class=""> }<br class=""><br class="">}<br class=""><br class="">The downside of this approach is the need to manage CopyInitializable<br class="">conformance of the types that becomes extra hassle that seems to<br class="">conflict with the behavior of value types.<br class=""></blockquote><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">It also, in generic code, undermines one of the great strengths of value</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">types: that we don't have to worry about defensively copying them just</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">to avoid unwanted side-effects.</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">I know it implies a fair bit of magic, but I suggest we consider a</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">system where you could write</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> extension Transmogrify where Self : Clonable {</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> public func transmogrified() -> Self {</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> var result = self // <========</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> result.transmogrify()</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> return result</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> }</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class=""> }</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">and in this context, a class that conformed to Clonable would be</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">implicitly cloned on the specified line. An immutable final class could</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">implement clone() as "return self"</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">This pitch proposes adding CopyInitializable protocol to the swift standard library and having the<br class="">compiler automatically generate conformance to it for all value types.<br class="">This would immediately solve all problems of correct convenient implementations of non-mutaiting<br class="">variants of in-place functions as well as remove the hassle of having to manage conformance to<br class="">CopyInitializable for all value types that are guaranteed to have this behavior in the first place.<br class=""><br class="">An good use case would be the NSNumber class, which would conform to CopyInitializable and make use<br class="">of a single obvious mutating-to-nonmutating implementation of arithmetic operations that would work<br class="">equally well on all standard numeric types.<br class=""><br class="">I’d like to hear opinions regarding this pitch and in case of consensus, I’d write an official<br class="">proposal and offer it for review.<br class=""><br class="">Regards,<br class="">Gor Gyolchanyan.<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""><br class=""></blockquote><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">--<span class="Apple-converted-space"> </span></span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">-Dave</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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 style="font-family: AvenirNext-Regular; font-size: 14px; 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; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><a href="mailto:swift-evolution@swift.org" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: AvenirNext-Regular; font-size: 14px; 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=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: AvenirNext-Regular; font-size: 14px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></div></body></html>