<div dir="ltr"><div><font face="arial, helvetica, sans-serif"><b>Situation</b></font></div><div><font face="arial, helvetica, sans-serif">Currently </font><font face="monospace, monospace">GeneratorType.next()</font><font face="arial, helvetica, sans-serif"> requires callers to not call </font><font face="monospace, monospace">next()</font><font face="arial, helvetica, sans-serif"> after it has returned </font><font face="monospace, monospace">nil</font><font face="arial, helvetica, sans-serif"> once, even encouraging a </font><font face="monospace, monospace">preconditionFailure()</font><font face="arial, helvetica, sans-serif"> if this is violated:</font></div><div><br></div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(181,181,181)"><span style="color:rgb(66,66,66)"> </span>/// - <span style="color:rgb(121,121,121)">Requires</span>: `next()` has not been applied to a copy of `self`</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(181,181,181)"><span style="color:rgb(66,66,66)"> </span>/// since the copy was made, and no preceding call to `self.next()`</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(181,181,181)"><span style="color:rgb(66,66,66)"> </span>/// has returned `nil`. Specific implementations of this protocol</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(181,181,181)"><span style="color:rgb(66,66,66)"> </span>/// are encouraged to respond to violations of this requirement by</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(181,181,181)"><span style="color:rgb(66,66,66)"> </span>/// calling `preconditionFailure("...")`.</p><div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">However, all </font><font face="arial, helvetica, sans-serif">28 GeneratorTypes in the standard library</font><span style="font-family:arial,helvetica,sans-serif"> actually do return nil on repeated calls past the end.</span><br></div><div><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div><span style="font-family:arial,helvetica,sans-serif"><br></span></div><div><font face="arial, helvetica, sans-serif"><b>Silent corner case</b></font></div><div><span style="font-family:arial,helvetica,sans-serif">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 (breaking the requirement) and that will almost always work – until someone passes in a GeneratorType that actually does raise the recommended preconditionFailure(). It becomes a silent corner case.</span></div><div><br></div><div><font face="arial, helvetica, sans-serif"><b>Adds caller burden</b></font></div><div><span style="font-family:arial,helvetica,sans-serif">To avoid breaking the requirement, the caller will not uncommonly have to track extra state and branch (e.g. keep a done/atEnd boolean). For example the UTF-8 & UTF-16 decoders do this (incidentally introducing an extra branch into a hot code path), while the UTF-32 decoder doesn't actually check – passing the requirement on to its caller (without this being documented). From personal experience implementing several custom generators I've found that respecting the requirement invariably adds complexity to the implementation.</span></div><div><br></div><div><font face="arial, helvetica, sans-serif"><b>Doesn't prevent bugs</b></font></div><div><span style="font-family:arial,helvetica,sans-serif">There seems to be little advantage to having it crash on past-the-end calls to next(). So far I haven't seen any examples where not crashing would silently hide a bug – and again even if there was it wouldn't help much considering almost no generators actually do crash.</span></div><div><div><br></div><div><font face="arial, helvetica, sans-serif"><b><br></b></font></div><div><font face="arial, helvetica, sans-serif"><b>Proposal</b></font></div></div></div><div>Change the guarantee for GeneratorType.next() to keep returning nil indefinitely after it has been exhausted.</div></div>