<div dir="ltr">Hmm I see.<div><br></div><div>Do we have any example cases where returning nil repeatedly would require extra branches or state?</div><div><br></div><div>The generators in the standard library don't (*) – the usual pattern is either of the following: </div><div>- 1) Check state if we're at end, if so return nil 2) get return value 3) advance state. Since the state is not mutated before returning nil, repeating nil is automatic.</div><div>- 1) Call next() on one or more wrapped generators 2) return some transformation of that. If the wrapped generators repeat nil, repeating nil is also automatic for the wrapper.</div><div><br></div><div>If you would have a generator setup that doesn't automatically repeat nil, omitting a nil-repeat check might be dangerous considering the risk other code hadn't considered the case.</div><div><br></div><div>(*) StrideThroughGenerator & ZipGenerator have a done flag, but need these even without repeating nil. JoinGenerator has an .End state but actually doesn't have to – even to repeat nil.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 3, 2016 at 8:12 PM, Dmitri Gribenko <span dir="ltr"><<a href="mailto:gribozavr@gmail.com" target="_blank">gribozavr@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Wed, Mar 2, 2016 at 10:47 PM, Patrick Pijnappel via swift-evolution<br>
<<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
> Situation<br>
> Currently GeneratorType.next() requires callers to not call next() after it<br>
> has returned nil once, even encouraging a preconditionFailure() if this is<br>
> violated:<br>
><br>
> /// - Requires: `next()` has not been applied to a copy of `self`<br>
> /// since the copy was made, and no preceding call to `self.next()`<br>
> /// has returned `nil`. Specific implementations of this protocol<br>
> /// are encouraged to respond to violations of this requirement by<br>
> /// calling `preconditionFailure("...")`.<br>
<br>
</span>I'd like to add more context to this discussion. We added this<br>
requirement a while ago. [1] The reason for introducing it was not<br>
an attempt to flag bugs in client code. Rather, we were not convinced<br>
that all generators can return nil repeatedly without loss of<br>
efficiency or extra storage burden.<br>
<br>
[1] <a href="https://github.com/apple/swift/commit/304b4f33ae74a5abd09da485bbc435dfa2ade522" rel="noreferrer" target="_blank">https://github.com/apple/swift/commit/304b4f33ae74a5abd09da485bbc435dfa2ade522</a><br>
and rdar://problem/17392226<br>
<span class=""><br>
> Adds caller burden<br>
> To avoid breaking the requirement, the caller will not uncommonly have to track extra state and branch<br>
<br>
</span>I would actually say the opposite -- running a non-trivial algorithm<br>
on generators is a very uncommon thing to do. The 99% use case for<br>
generators is implicit usage from the for-in loop. This is why<br>
allowing generators to be as simple as possible and pushing the<br>
requirement for extra branches into non-trivial algorithms made sense<br>
for us when we introduced this requirement.<br>
<span class=""><br>
> Silent corner case<br>
> Because basically all generators keep returning nil, it's not unlikely people will write their code based on the assumption it will always return nil<br>
<br>
</span>This is what concerns me the most about the current rules.<br>
<span class="HOEnZb"><font color="#888888"><br>
Dmitri<br>
<br>
--<br>
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if<br>
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <<a href="mailto:gribozavr@gmail.com">gribozavr@gmail.com</a>>*/<br>
</font></span></blockquote></div><br></div>