Hello, Swift Evolution!
The second review of SE-0516: Iterable has concluded. This revision review was focused on the API naming, and throwing iteration. The Language Steering Group has decided that the proposal is accepted with modifications.
One of the major topics throughout both review discussions was bulk iteration. The LSG agrees with the justification in the proposal that the bulk iteration model is a critical part of improving performance when working with a wide variety of collections; minimizing the calls to nextSpan(), which may cross a module boundary, allows optimizing iteration in ways that would not be possible if an ABI boundary must be crossed at each iteration to get the next element.
The primary discussion topic of the revision review was the API names, with a particular focus on the iterator APIs. The review discussion converged on the idea to keep the name Iterable for the main protocol, and use the BorrowingIterator terminology for the iterator API family. This preserves an approachable name for the primary protocol that communicates supporting any type that can be iterated, which is what most programmers will interact with, while communicating the important ownership concept behind iteration in the iterator API names, which will primarily be used by implementors of the protocol who need to have a deeper understanding of those mechanics. The proposal authors updated the proposed names based on this suggestion, and the LSG agrees this is the best choice.
There was also substantial discussion on the topic of end-of-iteration and post-throw policy. The review was extended to discuss the following API contract:
- Once the iterator returns an empty span, all subsequent calls to
nextSpanmust also return an empty span. - After an iterator throws an error, callers are expected to not call
nextSpanagain. This avoids a need to accept additional overhead in generic iterators that abstract over both throwing and non-throwing iterator types while preserving predictable semantics across Iterable types. Use cases that need to support recoverable errors can instead model that using a non-throwing iterator ofResults.
The remainder of the debate focused on whether the API contract for throwing iteration should be a rule for implementors of conformances to Iterable, or a rule for callers of the protocol’s requirements. The LSG decided that the API contract specified as a rule for the caller is the best tradeoff; prescribing specific behavior to implementations would impose additional overhead in some abstract iterators in order to keep track of whether previous calls threw an error in order to continue throwing, undermining the performance motivations behind introducing a new kind of iteration. Specifying the API contract as a rule for caller’s still preserves predictable semantics across Iterable types. The expectation is that use cases that need to support recoverable errors should not be modeled using a throwing conformance to Iterator, and should instead use a different abstraction or use a non-throwing iterator of Results.
A few other minor points were raised during, resulting in the following additional modifications:
OutputSpanandOutputRawSpanshould conform toIterablemaximumCountwill be renamed tomaxCountto match precedents elsewhere in the standard library.
Thank you to everyone who participated in the pitch and proposal review. Your contributions help make Swift a better language.
Holly Borla Review Manager