Skip to content

Commit

Permalink
Fix ProductIterator regression by using custom MaybeValue wrapper
Browse files Browse the repository at this point in the history
MaybeValue is just a simplified version of Nullable reserved for internal
use which wraps a value or no value in a type-stable way. Information
about whether a value is present or not is carried separately.
  • Loading branch information
nalimilan committed Dec 15, 2017
1 parent c0053f0 commit ec91f63
Showing 1 changed file with 14 additions and 6 deletions.
20 changes: 14 additions & 6 deletions base/iterators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Methods for working with Iterators.
"""
module Iterators

import Base: start, done, next, isempty, length, size, eltype, iteratorsize, iteratoreltype, axes, ndims, pairs, last, first
import Base: start, done, next, isempty, length, size, eltype, iteratorsize, iteratoreltype, axes, ndims, pairs, last, first, get

using Base: tail, tuple_type_head, tuple_type_tail, tuple_type_cons, SizeUnknown, HasLength, HasShape,
IsInfinite, EltypeUnknown, HasEltype, OneTo, @propagate_inbounds, Generator, AbstractRange
Expand Down Expand Up @@ -746,17 +746,25 @@ function next(P::ProductIterator, state)
end
done(P::ProductIterator, state) = state[1]

struct MaybeValue{T}
x::T
MaybeValue{T}() where {T} = new{T}()
MaybeValue{T}(x::T) where {T} = new{T}(x)
end

get(v::MaybeValue) = v.x

_prod_start(iterators::Tuple{}) = false, (), ()
function _prod_start(iterators)
iter1 = first(iterators)
state1 = start(iter1)
d, tailstates, tailnvalues = _prod_start(tail(iterators))
if done(iter1, state1)
d = true
nvalue1 = nothing
nvalue1 = MaybeValue{eltype(iter1)}()
else
value1, state1 = next(iter1, state1)
nvalue1 = Some{eltype(iter1)}(value1)
nvalue1 = MaybeValue{eltype(iter1)}(value1)
end
return (d, (state1, tailstates...), (nvalue1, tailnvalues...))
end
Expand All @@ -767,15 +775,15 @@ function _prod_next(iterators, states, nvalues)
state1 = first(states)
if !done(iter1, state1)
value1, state1 = next(iter1, state1)
nvalue1 = Some{eltype(iter1)}(value1)
nvalue1 = MaybeValue{eltype(iter1)}(value1)
return false, (state1, tail(states)...), (nvalue1, tail(nvalues)...)
else
d, tailstates, tailnvalues = _prod_next(tail(iterators), tail(states), tail(nvalues))
if d # all iterators are done
nvalue1 = nothing
nvalue1 = MaybeValue{eltype(iter1)}()
else
value1, state1 = next(iter1, start(iter1)) # iter cannot be done immediately
nvalue1 = Some{eltype(iter1)}(value1)
nvalue1 = MaybeValue{eltype(iter1)}(value1)
end
return d, (state1, tailstates...), (nvalue1, tailnvalues...)
end
Expand Down

0 comments on commit ec91f63

Please sign in to comment.