[Pitch] Remove the single-pass requirement on Sequence

It just occured to me after posting that there should be no way for Sequence to provide default implementations for non-mutating functions with only the mutating next function.

It seems the default implementations make a copy of self, making such a sequence multi-pass.

1 Like

big mood

...or a reference type.

You may be misunderstanding me. In the following code, it seems map is copying self:

code
struct NumberSequence: IteratorProtocol, Sequence {
    var nextItem = 0
    mutating func next() -> Int? {
        if nextItem == 10 {return nil}
        defer {nextItem += 1}
        return nextItem
    }
}

let s = NumberSequence()
let a = s.map{$0}
let b = s.map{$0} //b == a when NumberSequence is a struct

That aside, I agree that any single-pass sequence must have reference-sematics, to render this copying ineffective.

edit: …and all my reasoning on this topic so far was based on Iterators being single-pass when conformed to Sequence. So I'm back to square one, not understanding why Iterator and Sequence are separate protocols.

It occurs to me that perhaps this is a lack-of-moveonly issue. If Sequence.makeIterator() on a move-only type consumed self, then the type system would prevent you from treating a single-pass sequence as multi-pass, because any attempt to access the sequence's elements would destroy it.

Have we given any thought to how Sequence should look in a world with moveonly types? Have we thought about forward compatibility with such a future design?

4 Likes

Yep, they're intimately related. I think I had it all worked out at one point exactly how they should be related, but if so, I've since forgotten.

2 Likes

Too large to fit in the margin?

4 Likes