Related to SR-6691, I reworked the type described in the "Collection Protocols" section of the
LazySplitCollection sample type in the article "Conditional Conformance in the Standard Library" at the Swift Blog by @Ben_Cohen. The
LazyEmptyAdmittingUnlimitedSplitCollection type is the same as Ben's, the
LazyUnlimitedSplitCollection types introduce maximum split counts and empty sequence skipping, and
LazySplitCollection would be the final type to be actually submitted.
This project is actually a poor example of conditional conformance. The only thing you can actually optionally extend is make the
Hashable based on the wrapped collection's index type, and said optional conformance is automatically defined. A split collection can never be bidirectional because discovering when a split limit is reached is inherently forward-only. This may warrant including the variants without
maxSplits support (i.e.
maxSplits is infinite) in the Standard library, since there's no other way for bidirectional traversal.
For the types that support skipping empty subsequences, I had to use shenanigans with a
class to get around mutability restrictions when I need to set a cache on the first run of
startIndex. This has the benefit of making
isEmpty) amortized O(1) instead of O(n). The problem of using a cache is that mutating the wrapped collection ruins everything.
LazyFilterSequence calculates its
startIndex on demand, with a penalty of always running at near-O(n) time. Which way is better; should I change mine to match
I put the code in a gist, to see if anyone can check if I messed up anything, especially the various conditions of
LazySplitCollection when I run out of splits and/or various empty-subsequence states.
A bigger challenge to work on next:
LazySplitSequence. I have to somehow pass on a copy of a partially-expended wrapped-level iterator so the sequence-level iterator and use it for the next subsequence.