Skip to content

Commit 95f30a0

Browse files
committed
Make zip more complex & correct again
1 parent 83654b8 commit 95f30a0

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

base/iterators.jl

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -315,32 +315,44 @@ IteratorEltype(::Type{Zip{I,Z}}) where {I,Z} = and_iteratoreltype(IteratorEltype
315315
reverse(it::ZipHead) = ZipHead(reverse(it.a))
316316
reverse(it::Zip) = Zip(reverse(it.a), reverse(it.z))
317317

318-
# Iteration
319-
@inline function iterate(it::ZipHead, state...)
320-
isdone(it.a) === true && return nothing
321-
a = iterate(it.a, state...)
322-
a === nothing && return nothing
323-
((a[1],), a[2])
324-
end
318+
# the states are either Tuple{} or Tuple{Any}
319+
@inline function zip_iterate(a, z, sta, stz)
320+
da, dz = isdone(a), isdone(z)
321+
322+
# Note that stateless iterators vectorize provided there's no early return.
323+
# In the case of stateless iterators: all branches are removed compile-time
324+
# In the case of stateful iterators: the first condition is almost always true
325+
if da === dz === missing || da === dz === false
326+
ya, yz = iterate(a, sta...), iterate(z, stz...)
327+
ya === nothing && return nothing
328+
yz === nothing && return nothing
329+
elseif da === true || dz === true
330+
return nothing
331+
elseif da === missing
332+
# Iterate a only if z is not done and vice versa
333+
ya = iterate(a, sta...)
334+
ya === nothing && return nothing
335+
yz = iterate(z, stz...)
336+
yz === nothing && return nothing
337+
else
338+
yz = iterate(z, stz...)
339+
yz === nothing && return nothing
340+
ya = iterate(a, sta...)
341+
ya === nothing && return nothing
342+
end
325343

326-
@inline function iterate(it::Zip)
327-
isdone(it.a) === true && return nothing
328-
isdone(it.z) === true && return nothing
329-
a = iterate(it.a)
330-
z = iterate(it.z)
331-
a === nothing && return nothing
332-
z === nothing && return nothing
333-
((a[1], z[1]...), (a[2], z[2]))
344+
# Interleave the values
345+
val_a, state_a = ya
346+
val_z, state_z = yz
347+
return (val_a, val_z...), (state_a, state_z)
334348
end
335349

336-
@inline function iterate(it::Zip, state::Tuple{Any, Any})
350+
iterate(it::Zip) = zip_iterate(it.a, it.z, (), ())
351+
iterate(it::Zip, s::Tuple{Any, Any}) = zip_iterate(it.a, it.z, (s[1],), (s[2],))
352+
@inline function iterate(it::ZipHead, state...)
337353
isdone(it.a) === true && return nothing
338-
isdone(it.z) === true && return nothing
339-
a = iterate(it.a, state[1])
340-
z = iterate(it.z, state[2])
341-
a === nothing && return nothing
342-
z === nothing && return nothing
343-
((a[1], z[1]...), (a[2], z[2]))
354+
a = iterate(it.a, state...)
355+
return a === nothing ? nothing : ((a[1],), a[2])
344356
end
345357

346358
# filter

0 commit comments

Comments
 (0)