I've started work on a proposal that addresses the absence of lazy implementations of some Sequence-related operations.
In it I propose conforming all existing lazily implemented Sequences to LazySequenceProtocol:
Show / Hide
The following Sequences can't conform to LazySequenceProtocol because they don't contain an underlying Sequence and therefore can't conform to both Sequence and LazySequenceProtocol:
AnyBidirectionalCollection
AnyCollection
AnyIterator
AnyRandomAccessCollection
AnySequence
Array
ArraySlice
ClosedRange
CollectionOfOne
ContiguousArray
Dictionary
EmptyCollection
EmptyCollection.Iterator
KeyValuePairs
PartialRangeFrom
Range
Repeated
Set
StrideThrough
StrideTo
String
String.UnicodeScalarView
String.UTF16View
String.UTF8View
Substring
Substring.UnicodeScalarView
Substring.UTF16View
Substring.UTF8View
UnfoldSequence
Unicode.Scalar.UTF16View
UnsafeBufferPointer
UnsafeMutableBufferPointer
UnsafeMutableRawBufferPointer
UnsafeRawBufferPointer
UnsafeRawBufferPointer.Iterator
The following types can't conform to LazySequenceProtocol because they aren't sufficiently lazy:
DropFirstSequence
DropWhileSequence
DropFirstSequence can't conform to LazySequenceProtocol because makeIterator() pre-emptively drops the first k elements due to performance reasons. For the latter type a lazy implementation already exists.
The following Sequences already conform to LazySequenceProtocol and require no modifications:
LazyDropWhileSequence
LazyFilterSequence
LazyMapSequence
LazyPrefixWhileSequence
LazySequence
ReversedCollection
Slice
The following Sequences can conform to LazySequenceProtocol:
LazyFilterSequence.Iterator
LazyPrefixWhileSequence.Iterator
LazyMapSequence.Iterator
The following Sequences can conform to LazySequenceProtocol on the condition that Base conforms to LazySequenceProtocol:
EnumeratedSequence
EnumeratedSequence.Iterator
FlattenSequence
FlattenSequence.Iterator
IteratorSequence
JoinedSequence
PrefixSequence
ReversedCollection.Iterator
The conformance of FlattenSequence to LazySequenceProtocol means we can remove LazySequence from the return types of joined() and flatMap(_:) on LazySequenceProtocol. The old implementations can be deprecated. It also requires the explicit declaration of FlattenCollection.SubSequence.
The following Sequences can conform to LazySequenceProtocol on the condition that Elements conforms to LazySequenceProtocol:
DefaultIndices
IndexingIterator
Finally, Zip2Sequence can conform to LazySequenceProtocol on the condition that Sequence1 and Sequence2 conform to LazySequenceProtocol.
Then, for those inherited members from Sequence that still don't contain a lazy implementation on LazySequenceProtocol, overloads and types (conforming to LazySequenceProtocol and conventionally prefixed with Lazy) can be introduced:
-
dropFirst(_:) (LazyDropFirstSequence)
-
dropLast(_:) (LazyDropLastSequence)
-
reversed() (LazyReversedSequence)
-
shuffled() / shuffled(using:) (LazyShuffledSequence)
-
sorted() / sorted(by:) (LazySortedSequence)
-
split(maxSplits:omittingEmptySubsequences:isSeparator:) / split(separator:maxSplits:omittingEmptySubsequences:) (LazySplitSequence)
-
suffix(_:) (LazySuffixSequence)
But before I do any further work I want to gauge if this is the right direction to take so I can determine the scope of the proposal.
For instance, I can imagine some backlash against a lazy implementation that on the first call to next() requires the traversal of the entire underlying Sequence plus additional memoisation, like reversed().
Is this the right approach in your opinion? And if not, where would you draw the line for inclusion?