So here's what I'd intuitively write:
func process(_ array: [Int]) -> some LazySequence<Int> {
array.lazy.filter { 0 != $0 }
}
Unfortunately, LazySequence
is a struct, not a protocol. (it also requires its primary associated type be the type of the base sequence, [Int]
in this case, not the Element
, which is its own can of annoyance but irrelevant here)
There does exist LazySequenceProtocol
, but it has no primary associated type. So no bueno:
func process(_ array: [Int]) -> some LazySequenceProtocol<Int> {
array.lazy.filter { 0 != $0 }
}
Protocol 'LazySequenceProtocol' does not have primary associated types that can be constrained
(also, it complains that 'some' types are only permitted in properties, subscripts, and functions
which is confusingly irrelevant since some
is clearly being used in a legal place)
If I drop the primary associated type:
func process(_ array: [Int]) -> some LazySequenceProtocol {
array.lazy.filter { 0 != $0 }
}
…then it does technically work (compile) but of course the caller(s) of this are hassled by (some LazySequenceProtocol).Element
being undefined, requiring force-casting at the least.
Even if you forget about making the return type in any way opaque - assuming that's even a viable option in any given case - it's exceptionally ugly and tedious to do so if your lazy pipeline is non-trivial, since you end up with horrific function signatures like:
func process(_ array: [Int])
-> LazyFilterSequence<
LazyMapSequence<
LazyFilterSequence<
LazyMapSequence<
LazyFilterSequence<
LazySequence<
Array<Int>
>,
Int
>
>,
Int
>
>
> {
…
}