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 LazyEmptyAdmittingSplitCollection
and 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 Index
type 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 startIndex
(and 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 filter
's?
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.