<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 ran into this exact issue today. &nbsp;Would something like inout returns help to fix it?<div class=""><br class=""></div><div class="">I have a struct called StyledString which gets rid of much of the frustration of dealing with NSAttributedStrings in Swift. &nbsp;Basically, you make selections on the string and set some property of it like so:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>styled.paragraph(2).words(3…7).bold = true</div><div class=""><br class=""></div><div class="">and then at the end, you ask for an attributed string:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>myLabel.attributedText = styled.attributedString</div><div class=""><br class=""></div><div class="">The language I originally designed this for (almost 20 years ago) had a special type of function (called a selector) which could be in the middle of a chain of calls, but not at the end of it… which avoided the problem you are talking about here. &nbsp;In Swift, I basically have a note in the documentation saying not to store the selections in a variable… but that is not ideal. &nbsp;</div><div class=""><br class=""></div><div class="">It would be nice to have a way to say that the return value is not allowed to be stored (only called as part of a chain). &nbsp;This would allow mutable views without the issue of them breaking value semantics.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Jon</div><div class=""><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 27, 2017, at 9:08 AM, John McCall via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" 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="">3: Mutable Views</div><div class=""><br class=""></div><div class="">Currently a major pain point of Swift has been exposing “mutable views” into a type in a reasonable way. Apologies for length, but here’s an extended example:</div><div class=""><br class=""></div><div class="">&nbsp; /// Implements a 2D grid (of size fixed upon initialization).</div><div class="">&nbsp; /// **Not** a `Collection` itself but has many *views* into it that *are* `Collection`s.</div><div class="">&nbsp; ///</div><div class=""><div class="">&nbsp; struct Grid2D&lt;T&gt; {</div><div class="">&nbsp; &nbsp; // typical CoW backing storage</div><div class="">&nbsp; &nbsp; fileprivate var storage: Grid2DStorage&lt;T&gt;</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; /// Obtain a linear traversal of our grid:</div><div class="">&nbsp; &nbsp; /// - parameter corner: The corner at which we start (e.g. `northWest`)</div><div class="">&nbsp; &nbsp; /// - parameter motion: The order in which we travel (`latitudeThenLongitude` or `longitudeThanLatitude`)</div><div class="">&nbsp; &nbsp; ///</div><div class="">&nbsp; &nbsp; /// - returns: A read-only `Collection` that visits each grid location in `self`, following the requested traversal</div><div class="">&nbsp; &nbsp; func traversal(from corner: Grid2DCorner, following motion: Grid2DMotion) -&gt; Grid2DTraversal&lt;T&gt;</div><div class="">&nbsp; }</div></div><div class=""><br class=""></div><div class="">…wherein `Grid2DTraversal&lt;T&gt;` is, as noted, a "read-only view” into its parent that also adopts `Collection`.</div><div class=""><br class=""></div><div class="">What would be nice is to be able to make that `Grid2DTraversal&lt;T&gt;` into a mutable view in a way that’s also *safe*; what I mean is something like:</div><div class=""><br class=""></div><div class="">&nbsp; extension Grid2D {</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; mutating func mutatingTraversal&lt;T&gt;(from corner: Grid2DCorner, following motion: Grid2DMotion, _ mutator: (inout Grid2DTraversal&lt;T&gt;) -&gt; R) -&gt; R {</div><div class="">&nbsp; &nbsp; &nbsp; var t = self.traversal(from: corner, following: motion)</div><div class="">&nbsp; &nbsp; &nbsp; return mutator(&amp;t)</div><div class="">&nbsp; &nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">…with the specific goals of (a) having mutations applied via `Grid2DTraversal` get directly written-through to the underlying storage (w/out pointless copying) but also (b) making `Grid2DTraversal` generally act safely in all other contexts.</div><div class=""><br class=""></div><div class="">As it is the “best” way to squeeze this into the type system at this time is arguably:</div><div class=""><br class=""></div><div class="">- define Grid2DTraversal:</div><div class="">&nbsp; - to have as a strong reference to the backing storage</div><div class="">&nbsp; - as only having the read-only methods</div><div class="">- *also* define MutableGrid2DTraversal:</div><div class="">&nbsp; - to have an unowned reference to the backing storage</div><div class="">&nbsp; - also include the mutating methods</div><div class=""><br class=""></div><div class="">…and then just be careful with API design and patterns of use; in particular only provide access to `MutableGrid2DTraversal&lt;T&gt;` values in the context of closures passed into dedicated functions like `mutatingTraversal`, above…and then just be disciplined never to extract those passed-in values.</div><div class=""><br class=""></div><div class="">Needless to say this isn’t a very satisfactory state of affairs—it is well into “why am I bothering with all this?” territory—and it’d be *far* nicer if the ownership system would allow for `Grid2DTraversal`:</div><div class=""><br class=""></div><div class="">- to adopt `Collection` without restriction</div><div class="">- to adopt `MutableCollection` only in certain ownership contexts</div><div class="">- to have reasonable control over where those contexts apply&nbsp;</div></div></div></blockquote><div class=""><br class=""></div>It's not sensible to have a type that conditionally conforms to a protocol based on context. &nbsp;However, the requirements of MutableCollection are all 'mutating', so you can't actually use them unless you have a mutable value. &nbsp;So the way to fit what you're asking for into the ownership proposal is to make sure that clients of your view type only have a mutable value when the base was mutable, and the easiest way of getting that is to have the view be vended as storage rather than a return value. &nbsp;If you think about it, a mutable view can't be an independent value anyway, because if code like this could work:</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; var grid = ... // note that this is mutable</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; var view = grid.traversal(from: p, following: m) // should return a mutable view by design, right?</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; view.mutate() // reflected in grid, right?</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">then it completely destroys the value-type properties of 'grid', because 'view' should really be an independent value.</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">The proposal suggests doing this instead with storage, so that the view is logically a (mutable) component of the grid. &nbsp;So on the use side:</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; var grid = ...</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; inout view = &amp;grid[traversingFrom: p, following: m]</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; view.mutate()</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">and on the declaration side:</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; struct Grid2D&lt;T&gt; {</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; subscript(traversingFrom corner: Grid2DCorner, following motion: Grid2DMotion) -&gt; Grid2DTraversal&lt;T&gt; {</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; read {</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; yield Grid2DTraversal(...)</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; }</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; modify {</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; var traversal = Grid2DTraversal(...)</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; yield &amp;traversal</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; &nbsp; // ensure changes were applied here</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; &nbsp; }</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; &nbsp; }</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">&nbsp; }</div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; 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-stroke-width: 0px;" class="">If you feel that the aesthetics of this leave something to be desired, that's a totally reasonable thing to discuss.</div></div></blockquote></div><br class=""></div></div></body></html>