[swift-evolution] [Proposal] Change guarantee for GeneratorType.next() to always return nil past end
brent at architechies.com
Sat Mar 5 19:40:17 CST 2016
> In fact, I don't think the post-nil behavior of generators is even the biggest potential gotcha. A much bigger issue is how generators behave when you make copies of them. If you ever copy a generator you're supposed to never touch the original again, but it's easy to violate that accidentally, and most generators actually behave sanely when copied anyway.
That's true, but it's just not addressable until we have some kind of borrowing system in place.
>> (Another reason to lean towards always returning `nil`: it's testable. In fact, I was thinking it might be nice to have something in XCTest where you could hand it a Sequence, or perhaps a closure that creates one, and an array containing the values you expect it to have, and it would assert the basic properties we expect from a Sequence, like that the elements come out in the right order, it returns nil at the end, `underestimateCount()` is not incorrect, etc. The `nil` semantic, unlike the other possible ones, is something you could include in that test.)
> Defining the post-nil behavior as implementation-defined means that, by definition, you don't need to test how arbitrary generators behave there.
True, but then you're imposing a constraint on the clients of generators: "Don't call next() again after it turns nil". I think it will be far easier to write generic tests of any generator than it will be to write generic tests of any function that *uses* a generic generator.
(Although I suppose you could assist in that testing by writing a wrapper around any sequence/collection/generator which enforces all rules as strictly as possible.)
> Besides, you can't actually test that a given GeneratorType returns nil forever, you can only test that it returns nil for some finite number of calls to next(). It would be entirely possible to have a GeneratorType whose behavior depends on some external signal and will return nil until such time as that external signal has data again. For example, you could have a GeneratorType that reads lines from stdin in a non-blocking fashion, and so it would return nil until the user has typed another line of text. Or you could have a GeneratorType that represents an atomic FIFO queue and returns nil if the queue is empty.
That's true, but you can still usefully test the common cases.
More information about the swift-evolution