<div><br><div class="gmail_quote"><div dir="auto">Daryle Walker via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; schrieb am Di. 8. Aug. 2017 um 21:25:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Aug 8, 2017, at 12:35 AM, Félix Cloutier &lt;<a href="mailto:felixcloutier@icloud.com" target="_blank">felixcloutier@icloud.com</a>&gt; wrote:</div><br class="m_5940453953046347490Apple-interchange-newline"><div><div style="word-wrap:break-word"><div>All this means is that `joined()` does not create an array that contains the new result. It&#39;s only as magic as the COW semantics on arrays.</div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>So you’re saying the COW semantics for Array and other standard library types have secret references/pointers that work even for “let”-mode objects, and the Sequence variants the various forms of “joined” need use a Sequence/Collection of those secret references?</div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">I know nothing about this specific type under the hood and your question stumped me when I first saw it as well, so take this with a grain of salt:</div><div dir="auto"><br></div><div dir="auto">I think it&#39;s basically just storing the arrays internally (as let) and when you iterate through the collection it just goes through the subsequences one by one, when the last index of the first is reached it begins with the next subsequence.</div><div dir="auto"><br></div><div dir="auto">As for how it avoids creating new storage, simple. As someone else mentioned, this is no more magic than Copy On Write for normal arrays.</div><div dir="auto"><br></div><div dir="auto">let a = [1,2,3]</div><div dir="auto">let b = a // this doesn&#39;t produce a copy of the underlying buffer.. I.e. value semantics but only one buffer needed</div><div dir="auto"><br></div><div dir="auto">^^^ This is the take-home message. And your intuition about COW is correct: its internal storage is a reference type containing a buffer pointer. When (and only when) a mutation occurs, the buffer is copied and the new storage becomes the backing for the resulting struct. Any existing copies remain unchanged (and truly immutable) because they keep their original storage.</div><div dir="auto"><br></div><div dir="auto"><a href="https://github.com/apple/swift/blob/master/stdlib/public/core/ContiguousArrayBuffer.swift">https://github.com/apple/swift/blob/master/stdlib/public/core/ContiguousArrayBuffer.swift</a></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">So with that understanding of COW, it becomes easy to imagine all sorts of containers that don&#39;t require additional storage for their contents:</div><div dir="auto"><br></div><div dir="auto">struct JoinedSequenceOfThreeArrays&lt;T&gt; {</div><div dir="auto">  let array1: [T]</div><div dir="auto">  let array2: [T]</div><div dir="auto">  let array3: [T]</div><div dir="auto">}</div><div dir="auto"><br></div><div dir="auto">// still only one array buffer storage is required for all of this:</div><div dir="auto">let c = JoinedSequenceOfThreeArrays(array1: a, array2: a, array3: b)</div><div dir="auto"><br></div><div dir="auto">Does that make sense?</div><div dir="auto"><br></div><div dir="auto">Geordie</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div></div></div></div><div style="word-wrap:break-word"><div><div><br></div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><blockquote type="cite"><div>Le 7 août 2017 à 21:12, Daryle Walker via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; a écrit :</div><br class="m_5940453953046347490Apple-interchange-newline"><div><div style="word-wrap:break-word"><div>I was looking at random items at <a href="http://swiftdoc.org/" target="_blank">SwiftDoc.org</a>, and noticed the “FlattenBidirectionalCollection” structure. It helps implement some versions of “joined” from Sequence (probably when the Sequence is also a BidirectionalCollection). The directions for the type state that “joined” does not create new storage. Then wouldn’t it have to refer to the source objects by reference? How; especially how does it work without requiring a “&amp;” with “inout” or how it works with “let”-mode objects? Or am I misunderstanding how it works behind the covers?</div><div><br></div><div>(If there is a secret sauce to have one object refer to another without “&amp;”/“inout”/“UnsafeWhateverPointer”, I like to know. It may help with implementing an idea. The idea involves extending the language, so “compiler magic” that the user can’t access is OK; I’d just claim to use the same sauce in my proposal.)</div></div></div></blockquote></div></div></div></blockquote></div></div><div style="word-wrap:break-word"><br><div><div><div style="word-wrap:break-word"><div>— </div><div>Daryle Walker<br>Mac, Internet, and Video Game Junkie<br>darylew AT mac DOT com </div></div></div><br><div><blockquote type="cite"></blockquote></div></div></div>_______________________________________________<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" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div>