I've been playing around with parameter packs and trying to implement the body of ZipSequence.Iterator's next() method from SE-0398 with little success.
The code from the proposal for reference:
struct ZipSequence<each S: Sequence>: Sequence {
typealias Element = (repeat (each S).Element)
let seq: (repeat each S)
func makeIterator() -> Iterator {
return Iterator(iter: (repeat (each seq).makeIterator()))
}
struct Iterator: IteratorProtocol {
typealias Element = (repeat (each S).Element)
var iter: (repeat (each S).Iterator)
mutating func next() -> Element? {
return ???
}
}
}
func zip<each S>(
_ seq: repeat each S
) -> ZipSequence<repeat each S> where repeat each S: Sequence {
ZipSequence(seq: (repeat each seq))
}
I've tried using (repeat (each iter).next()) which results in the error `Cannot use mutating member on immutable value of type 'τ_1_0.Iterator'.
is there a way to implement this or does this require pack iteration to be implemented?
1 Like
xAlien95
(Stefano De Carolis)
2
From [Pitch] Parameter Packs - #93 by Slava_Pestov
4 Likes
A few weeks ago @hborla came up with an interesting workaround for the lack of mutable packs, sufficient to implement a ZipIterator. Behold:
enum Stop: Error {
case stop
}
struct ZipIterator<each T: IteratorProtocol>: IteratorProtocol {
var iter: (repeat each T)
init(_ iter: repeat each T) {
self.iter = (repeat each iter)
}
mutating func next() -> (repeat (each T).Element)? {
func step<I: IteratorProtocol>(_ iter: I) throws -> (I, I.Element) {
var iter2 = iter
guard let next = iter2.next() else { throw Stop.stop }
return (iter2, next)
}
do {
let result: (repeat (each T, (each T).Element)) = (repeat try step(each iter))
iter = (repeat (each result).0)
return (repeat (each result).1)
} catch {
return nil
}
}
}
var x = ZipIterator([1, 2, 3].makeIterator(), ["hi", "hello", "hey"].makeIterator())
print(x.next())
print(x.next())
print(x.next())
print(x.next())
Making this ergonomic is basically half of the parameter packs roadmap...
13 Likes