[swift-evolution] [Proposal] Change guarantee for GeneratorType.next() to always return nil past end

Patrick Pijnappel patrickpijnappel at gmail.com
Thu Mar 3 00:47:12 CST 2016

Currently GeneratorType.next() requires callers to not call next() after it
has returned nil once, even encouraging a preconditionFailure() if this is

  /// - Requires: `next()` has not been applied to a copy of `self`

  ///   since the copy was made, and no preceding call to `self.next()`

  ///   has returned `nil`.  Specific implementations of this protocol

  ///   are encouraged to respond to violations of this requirement by

  ///   calling `preconditionFailure("...")`.

However, all 28 GeneratorTypes in the standard library actually do return
nil on repeated calls past the end.

*Silent corner case*
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.

*Adds caller burden*
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.

*Doesn't prevent bugs*
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.

Change the guarantee for GeneratorType.next() to keep returning nil
indefinitely after it has been exhausted.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160303/e3508d04/attachment.html>

More information about the swift-evolution mailing list