Skip to content

Commit f68afde

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

File tree

1 file changed

+40
-20
lines changed

1 file changed

+40
-20
lines changed

base/iterators.jl

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -315,32 +315,52 @@ 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])
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
343+
344+
return ya, yz
324345
end
325346

326347
@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]))
348+
y = zip_iterate(it.a, it.z, (), ())
349+
y === nothing && return nothing
350+
(val_a, state_a), (val_z, state_z) = y
351+
return (val_a, val_z...), (state_a, state_z)
334352
end
335-
336-
@inline function iterate(it::Zip, state::Tuple{Any, Any})
353+
@inline function iterate(it::Zip, s::Tuple{Any, Any})
354+
y = zip_iterate(it.a, it.z, (s[1],), (s[2],))
355+
y === nothing && return nothing
356+
(val_a, state_a), (val_z, state_z) = y
357+
return (val_a, val_z...), (state_a, state_z)
358+
end
359+
@inline function iterate(it::ZipHead, state...)
337360
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])
361+
a = iterate(it.a, state...)
341362
a === nothing && return nothing
342-
z === nothing && return nothing
343-
((a[1], z[1]...), (a[2], z[2]))
363+
((a[1],), a[2])
344364
end
345365

346366
# filter

0 commit comments

Comments
 (0)