<div dir="ltr">+1 on this. Scala also has a similar feature (copy constructor) for its case classes. Right now there&#39;s no generic way to do this in Swift, besides resorting to code generation.<div><br></div><div>Would this feature have an impact on the ABI and therefore be considered for Swift 4 part 1?</div><div><br></div><div>-Miguel</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 19, 2016 at 4:29 PM, Andy Chou via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Thanks Erica, I wasn&#39;t aware of that proposal. If I&#39;m reading it right, the proposed &#39;with&#39; function won&#39;t work for let-constants in structures, e.g.:<div><br></div><div><span class="">struct Person {<br>    let name: String<br>    let address: String<br>}<br><br></span><span class="">@discardableResult<br>public func with&lt;T&gt;(_ item: T, update: (inout T) throws -&gt; Void) <wbr>rethrows -&gt; T {<br>    var this = item<br>    try update(&amp;this)<br>    return this<br>}<br><br>let john = Person(name: &quot;John&quot;, address: &quot;1 battery st&quot;)<br></span>let jane: Person = with(john) { $<a href="http://0.name" target="_blank">0.name</a> = &quot;Jane&quot; }   // Cannot assign to property: &#39;name&#39; is a &#39;let&#39; constant<span class="HOEnZb"><font color="#888888"><br><br><div>Andy</div></font></span><div><br><div><blockquote type="cite"><span class=""><div>On Dec 19, 2016, at 11:44 AM, Erica Sadun &lt;<a href="mailto:erica@ericasadun.com" target="_blank">erica@ericasadun.com</a>&gt; wrote:</div><br class="m_-4247371578732465887Apple-interchange-newline"></span><div><div class="h5"><div><div style="word-wrap:break-word"><div><a href="https://github.com/apple/swift-evolution/pull/346" target="_blank">https://github.com/apple/<wbr>swift-evolution/pull/346</a></div><div><br></div><div>Be aware that there&#39;s a bug that&#39;s being worked on:</div><div><br></div><div><a href="https://bugs.swift.org/browse/SR-2773" target="_blank">https://bugs.swift.org/browse/<wbr>SR-2773</a></div><div><br></div><div>-- E</div><div><br></div><br><div><blockquote type="cite"><div>On Dec 19, 2016, at 12:40 PM, Andy Chou via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-4247371578732465887Apple-interchange-newline"><div><div dir="auto"><div>Of course. Thanks for pointing out the obvious solution. This preserves the immutability of the struct and doesn&#39;t require O(n^2) code for structs with large numbers of fields. </div><div><br></div><div>I was thinking of a generic solution - perhaps something like a synthetic initializer that does what your solution does. But that may be overkill given how relatively easy it is to do this per struct...</div><div><br></div><div>On the other hand a generic solution would encourage using immutable structs. I wasted too much time trying to solve this, I suspect others would just give up and use var, or even classes. </div><div><br>Andy</div><div><br>On Dec 19, 2016, at 10:43 AM, Nick Keets &lt;<a href="mailto:nick.keets@gmail.com" target="_blank">nick.keets@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div>




<div name="messageBodySection">You are probably asking for a generic solution, but for a specific struct you can implement it like this:
<div><br></div>
<div><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(186,45,162)"><span style="font-variant-ligatures:no-common-ligatures">extension</span> <span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">Person</span> <span style="font-variant-ligatures:no-common-ligatures">{</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">   </span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">func</span> <span style="font-variant-ligatures:no-common-ligatures">with(name:</span> <span style="font-variant-ligatures:no-common-ligatures;color:#703daa">String</span><span style="font-variant-ligatures:no-common-ligatures">? =</span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">nil</span><span style="font-variant-ligatures:no-common-ligatures">, address:</span> <span style="font-variant-ligatures:no-common-ligatures;color:#703daa">String</span><span style="font-variant-ligatures:no-common-ligatures">? =</span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">nil</span><span style="font-variant-ligatures:no-common-ligatures">, phone:</span> <span style="font-variant-ligatures:no-common-ligatures;color:#703daa">String</span><span style="font-variant-ligatures:no-common-ligatures">? =</span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">nil</span><span style="font-variant-ligatures:no-common-ligatures">) -&gt;</span> <span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">Person</span> <span style="font-variant-ligatures:no-common-ligatures">{</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">       </span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">let</span> <span style="font-variant-ligatures:no-common-ligatures">name = name ??</span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">self</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">name</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">       </span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">let</span> <span style="font-variant-ligatures:no-common-ligatures">address = address ??</span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">self</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">address</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">       </span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">let</span> <span style="font-variant-ligatures:no-common-ligatures">phone = phone ??</span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">self</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">phone</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">       </span> <span style="font-variant-ligatures:no-common-ligatures;color:#ba2da2">return</span> <span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">Person</span><span style="font-variant-ligatures:no-common-ligatures">(name: name, address: address, phone: phone)</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">    }</span></div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div>
</div>
<div><span style="font-variant-ligatures:no-common-ligatures"><br></span></div>
</div>
<div name="messageReplySection"><br>
On 19 Dec 2016, 20:28 +0200, Andy Chou via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;, wrote:<br>
<blockquote type="cite" style="margin:5px 5px;padding-left:10px;border-left:thin solid #1abc9c">I like that structs are value types in Swift, this encourages the use of immutable data. O&#39;Caml has an operator &quot;with&quot; that allows for copying an existing struct with a change to one field. I looked at Lenses for this functionality and it seems like a lot to digest for something so simple. I also tried to implement this using a constructor, or a function, and it was not obvious how to do so without a lot of code duplication.<br>
<br>
What&#39;s I&#39;m looking for is something like this (not necessarily with this syntax):<br>
<br>
struct Person {<br>
let name: String<br>
let address: String<br>
let phone: String<br>
}<br>
<br>
func f() {<br>
let andy = Person(name: &quot;Andy&quot;, address: &quot;1 Battery St., San Francisco, CA&quot;, phone: &quot;1234567&quot;)<br>
let chris = andy.with(name: &quot;Chris&quot;)<br>
let dave = andy.with(address: &quot;50 Townsend St., San Francisco, CA&quot;)<br>
}<br>
<br>
I tried to implement a &quot;with&quot; function like this but default arguments cannot reference properties of self. Same problem trying to do this in a constructor.<br>
<br>
Obviously it&#39;s possible to create an entirely new Person specifying the values from an existing Person, but this is very tedious with structures with many properties.<br>
<br>
Anyone taken a look at this before? Any suggestions?<br>
<br>
Andy<br>
<br>
______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></blockquote>
</div>


</div></blockquote></div>______________________________<wbr>_________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></blockquote></div><br></div></div></div></div></blockquote></div><br></div></div></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>