<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 12, 2016, at 11:55 AM, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 11, 2016, at 18:35 , plx via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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;"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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;"><b class="">RandomElementSequence</b>: As you say, this type is copyable, but its iteration is destructive: you can't get back to a previous state via any sort of Index. But that's not a distinction between Sequence and Generator today; there are some Generators that are perfectly copyable and others that are not. (Ideally, the ones that aren't would be made into classes.) If all you have is a generic Generator, you can only iterate it once…but the same is true of Sequence. Knowing the concrete type&nbsp;</div></div></blockquote><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: 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: 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="">^ did something get edited out here?</div></div></div></div></blockquote></div><br class=""><div class="">Oops, yes. "Knowing the concrete type is the only way to guarantee that multiple iteration is safe." And then:</div><div class=""><br class=""></div><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div class=""><blockquote type="cite" class="">Sure, you could come up with a new protocol, MultipassSequence, but you could just as easily have a MultipassGenerator that just means "this generator is safe to copy". (That's basically&nbsp;<a href="http://en.cppreference.com/w/cpp/iterator" class="">InputIterator vs. ForwardIterator</a>&nbsp;in C++.)</blockquote></div></div></blockquote></div></div><div class=""><div class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Also:</div><div class=""><br class=""></div><div class=""></div><blockquote type="cite" class=""><div class="">It also highlights that `ForwardIndexType` and `GeneratorType` are suspiciously similar, and would be even more so in a “collections move indices” world (e.g. SR-122, which I hope is adopted in some form).</div></blockquote><div class=""><br class=""></div><div class="">I guess this is true, in that both produce a single successor, but (a) ForwardIndexType is non-destructive whereas GeneratorType may be, and (b) in that new model, ForwardIndexType does <i class="">not</i>&nbsp;know its successor whereas GeneratorType <i class="">does.</i></div></div></div></div></div></blockquote><div><br class=""></div><div>It’s not so much that they both produce a single successor; it’s that both of them can wind up with most of their “interesting" logic essentially-shared.</div><div><br class=""></div><div>Consider the following thought experiment:</div><div><br class=""></div><div>protocol AlternativeCollectionType {</div><div>&nbsp; typealias InternalPosition: Equatable</div><div>&nbsp; typealias Item // so-named so as to avoid some later circularity</div><div>&nbsp;&nbsp;</div><div>&nbsp; var startPosition: InternalPosition&nbsp;{ get }</div><div>&nbsp; var endPosition: InternalPosition&nbsp;{ get }</div><div>&nbsp; subscript(position: InternalPosition) -&gt; Item { get }</div><div><br class=""></div><div>&nbsp; // - requires: `position != endPosition`</div><div>&nbsp; func successorFor(position: InternalPosition) -&gt; InternalPosition</div><div>&nbsp;&nbsp;</div><div>}</div><div><br class=""></div><div>// assume `==` just examines position (which seems fair here):</div><div>struct ConcretePosition&lt;C:AlternativeCollectionType&gt; : Equatable {</div><div>&nbsp; typealias Element = C.Item</div><div><br class=""></div><div>&nbsp; private let collection: C</div><div>&nbsp; private var position: C.InternalPosition</div><div><br class=""></div><div>&nbsp; func isEndPosition() -&gt; Bool {</div><div>&nbsp; &nbsp; return position == collection.endPosition</div><div>&nbsp; }</div><div><br class=""></div><div>&nbsp; func dereference() -&gt; Element? {</div><div>&nbsp; &nbsp; if isEndPosition() { return nil }</div><div>&nbsp; &nbsp; return collection[position]</div><div>&nbsp; }</div><div><br class=""></div><div>&nbsp; private func nextPosition() -&gt; C.InternalPosition&nbsp;{</div><div>&nbsp; &nbsp; precondition(!isEndPosition())</div><div>&nbsp; &nbsp; return collection.successorFor(position)</div><div>&nbsp; }</div><div><br class=""></div><div>}</div><div><br class=""></div><div>extension ConcretePosition : ForwardIndexType {</div><div>&nbsp; func successor() -&gt; ConcretePosition&lt;C&gt; {&nbsp;</div><div>&nbsp; &nbsp; return ConcretePosition&lt;C&gt;(</div><div>&nbsp; &nbsp; &nbsp; collection: collection,</div><div>&nbsp; &nbsp; &nbsp; position: nextPosition()</div><div>&nbsp; &nbsp; )</div><div>&nbsp; }</div><div>}</div><div><br class=""></div><div>extension ConcretePosition: GeneratorType {</div><div>&nbsp; mutating func next() -&gt; Element? {</div><div>&nbsp; &nbsp; guard let element = dereference() else { return nil }</div><div>&nbsp; &nbsp; position = nextPosition()</div><div>&nbsp; &nbsp; return element</div><div>&nbsp; }</div><div>}</div><div><br class=""></div><div>I think the *similarity* under this organization is pretty straightforward; although `successor()` and `next()` are definitely *not* identical, they can both be implemented as operations on the same base type, with a lot the logic being essentially common to both (that’s the part written here as `nextPosition`, which simply calls the collection's `successorFor`).</div><div><br class=""></div><div><div><div>Note that under Swift’s current organization, that common logic winds up manually-inlined into both `next` and `successor`, often in ways that make the commonality harder to spot.</div><div class=""><br class=""></div></div></div><div><div>The above experiment’s connection-with “collections move indices” is also I hope pretty easy to spot; if you accept the premise that most concrete `ForwardIndexType` implementations will in fact need a back-reference — or the moral equivalent thereof — to be able to implement the ostensibly stand-alone `successor()`, then it seems reasonable to consider the possibility that the stand-alone `successor` is actually the special-case (a very handy case, but still a special case); if you don’t accept that premise, we’ll have to agree to disagree.</div><div><br class=""></div><div>Thanks again for the consideration and the considered replies. I will be finishing up a proposal relating to this topic and it’ll be much the better for having received your responses (and Dmitri’s, also).</div></div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div class=""><i class=""><br class=""></i></div><div class="">Jordan</div></div></div></div></div></blockquote></div><br class=""></body></html>