Skip to content

Commit

Permalink
Remove NoInit() and use optional keyword argument
Browse files Browse the repository at this point in the history
Hack utilizes varargs form of keyword arguments.
  • Loading branch information
Andy Ferris committed Jun 28, 2018
1 parent 981b341 commit 1a582a3
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 44 deletions.
58 changes: 30 additions & 28 deletions base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ mul_prod(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) * UInt(y)

## foldl && mapfoldl

@noinline function mapfoldl_impl(f, op, init, itr, i...)
@noinline function mapfoldl_impl(f, op, nt::NamedTuple{(:init,)}, itr, i...)
init = nt.init
# Unroll the while loop once; if init is known, the call to op may
# be evaluated at compile time
y = iterate(itr, i...)
Expand All @@ -56,32 +57,32 @@ mul_prod(x::SmallUnsigned,y::SmallUnsigned) = UInt(x) * UInt(y)
return v
end

function mapfoldl_impl(f, op, ::NoInit, itr)
function mapfoldl_impl(f, op, nt::NamedTuple{()}, itr)
y = iterate(itr)
if y === nothing
return Base.mapreduce_empty_iter(f, op, itr, IteratorEltype(itr))
end
(x, i) = y
init = mapreduce_first(f, op, x)
mapfoldl_impl(f, op, init, itr, i)
mapfoldl_impl(f, op, (init=init,), itr, i)
end


"""
mapfoldl(f, op, itr; init=Base.NoInit())
mapfoldl(f, op, itr; [init])
Like [`mapreduce`](@ref), but with guaranteed left associativity, as in [`foldl`](@ref).
If provided, `init` will be used exactly once. In general, it will be necessary to provide
`init` to work with empty collections.
If provided, the keyword argument `init` will be used exactly once. In general, it will be
necessary to provide `init` to work with empty collections.
"""
mapfoldl(f, op, itr; init=NoInit()) = mapfoldl_impl(f, op, init, itr)
mapfoldl(f, op, itr; kw...) = mapfoldl_impl(f, op, kw.data, itr)

"""
foldl(op, itr; init=Base.NoInit())
foldl(op, itr; [init])
Like [`reduce`](@ref), but with guaranteed left associativity. If provided, `init` will be
used exactly once. In general, it will be necessary to provide `init` to work with empty
collections.
Like [`reduce`](@ref), but with guaranteed left associativity. If provided, the keyword
argument `init` will be used exactly once. In general, it will be necessary to provide
`init` to work with empty collections.
# Examples
```jldoctest
Expand All @@ -92,11 +93,12 @@ julia> foldl(=>, 1:4; init=0)
(((0=>1)=>2)=>3) => 4
```
"""
foldl(op, itr; init=NoInit()) = mapfoldl(identity, op, itr; init=init)
foldl(op, itr; kw...) = mapfoldl(identity, op, itr; kw...)

## foldr & mapfoldr

function mapfoldr_impl(f, op, init, itr, i::Integer)
function mapfoldr_impl(f, op, nt::NamedTuple{(:init,)}, itr, i::Integer)
init = nt.init
# Unroll the while loop once; if init is known, the call to op may
# be evaluated at compile time
if isempty(itr) || i == 0
Expand All @@ -112,29 +114,29 @@ function mapfoldr_impl(f, op, init, itr, i::Integer)
end
end

function mapfoldr_impl(f, op, ::NoInit, itr, i::Integer)
function mapfoldr_impl(f, op, ::NamedTuple{()}, itr, i::Integer)
if isempty(itr)
return Base.mapreduce_empty_iter(f, op, itr, IteratorEltype(itr))
end
return mapfoldr_impl(f, op, mapreduce_first(f, op, itr[i]), itr, i-1)
return mapfoldr_impl(f, op, (init=mapreduce_first(f, op, itr[i]),), itr, i-1)
end

"""
mapfoldr(f, op, itr; init=Base.NoInit())
mapfoldr(f, op, itr; [init])
Like [`mapreduce`](@ref), but with guaranteed right associativity, as in [`foldr`](@ref). If
provided, `init` will be used exactly once. In general, it will be necessary to provide
`init` to work with empty collections.
provided, the keyword argument `init` will be used exactly once. In general, it will be
necessary to provide `init` to work with empty collections.
"""
mapfoldr(f, op, itr; init=NoInit()) = mapfoldr_impl(f, op, init, itr, lastindex(itr))
mapfoldr(f, op, itr; kw...) = mapfoldr_impl(f, op, kw.data, itr, lastindex(itr))


"""
foldr(op, itr; init=Base.NoInit())
foldr(op, itr; [init])
Like [`reduce`](@ref), but with guaranteed right associativity. If provided, `init` will be
used exactly once. In general, it will be necessary to provide `init` to work with empty
collections.
Like [`reduce`](@ref), but with guaranteed right associativity. If provided, the keyword
argument `init` will be used exactly once. In general, it will be necessary to provide
`init` to work with empty collections.
# Examples
```jldoctest
Expand All @@ -145,7 +147,7 @@ julia> foldr(=>, 1:4; init=0)
1 => (2=>(3=>(4=>0)))
```
"""
foldr(op, itr; init=NoInit()) = mapfoldr(identity, op, itr; init=init)
foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...)

## reduce & mapreduce

Expand Down Expand Up @@ -183,7 +185,7 @@ mapreduce_impl(f, op, A::AbstractArray, ifirst::Integer, ilast::Integer) =
mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op))

"""
mapreduce(f, op, itr; init=Base.NoInit())
mapreduce(f, op, itr; [init])
Apply function `f` to each element in `itr`, and then reduce the result using the binary
function `op`. If provided, `init` must be a neutral element for `op` that will be returne
Expand All @@ -206,7 +208,7 @@ implementations may reuse the return value of `f` for elements that appear multi
`itr`. Use [`mapfoldl`](@ref) or [`mapfoldr`](@ref) instead for
guaranteed left or right associativity and invocation of `f` for every value.
"""
mapreduce(f, op, itr; init=NoInit()) = mapfoldl(f, op, itr; init=init)
mapreduce(f, op, itr; kw...) = mapfoldl(f, op, itr; kw...)

# Note: sum_seq usually uses four or more accumulators after partial
# unrolling, so each accumulator gets at most 256 numbers
Expand Down Expand Up @@ -330,7 +332,7 @@ mapreduce(f, op, a::Number) = mapreduce_first(f, op, a)
_mapreduce(f, op, ::IndexCartesian, A::AbstractArray) = mapfoldl(f, op, A)

"""
reduce(op, itr; init=Base.NoInit())
reduce(op, itr; [init])
Reduce the given collection `itr` with the given binary operator `op`. If provided, the
initial value `init` must be a neutral element for `op` that will be returned for empty
Expand Down Expand Up @@ -362,7 +364,7 @@ julia> reduce(*, [2; 3; 4]; init=-1)
-24
```
"""
reduce(op, itr; init=NoInit()) = mapreduce(identity, op, itr; init=init)
reduce(op, itr; kw...) = mapreduce(identity, op, itr; kw...)

reduce(op, a::Number) = a # Do we want this?

Expand Down
24 changes: 11 additions & 13 deletions base/reducedim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ reducedim!(op, R::AbstractArray{RT}, A::AbstractArray) where {RT} =
mapreducedim!(identity, op, R, A)

"""
mapreduce(f, op, A::AbstractArray; dims=:, init=Base.NoInit())
mapreduce(f, op, A::AbstractArray; dims=:, [init])
Evaluates to the same as `reduce(op, map(f, A); dims=dims, init=init)`, but is generally
faster because the intermediate array is avoided.
Expand All @@ -271,24 +271,24 @@ julia> mapreduce(isodd, |, true, a, dims=1)
true true true true
```
"""
mapreduce(f, op, A::AbstractArray; dims=:, init=NoInit()) = _mapreduce_dim(f, op, init, A, dims)
mapreduce(f, op, A::AbstractArray; dims=:, kw...) = _mapreduce_dim(f, op, kw.data, A, dims)

_mapreduce_dim(f, op, init, A::AbstractArray, ::Colon) = mapfoldl(f, op, A; init=init)
_mapreduce_dim(f, op, nt::NamedTuple{(:init,)}, A::AbstractArray, ::Colon) = mapfoldl(f, op, A; nt...)

_mapreduce_dim(f, op, ::NoInit, A::AbstractArray, ::Colon) = _mapreduce(f, op, IndexStyle(A), A)
_mapreduce_dim(f, op, ::NamedTuple{()}, A::AbstractArray, ::Colon) = _mapreduce(f, op, IndexStyle(A), A)

_mapreduce_dim(f, op, init, A::AbstractArray, dims) =
mapreducedim!(f, op, reducedim_initarray(A, dims, init), A)
_mapreduce_dim(f, op, nt::NamedTuple{(:init,)}, A::AbstractArray, dims) =
mapreducedim!(f, op, reducedim_initarray(A, dims, nt.init), A)

_mapreduce_dim(f, op, ::NoInit, A::AbstractArray, dims) =
_mapreduce_dim(f, op, ::NamedTuple{()}, A::AbstractArray, dims) =
mapreducedim!(f, op, reducedim_init(f, op, A, dims), A)

"""
reduce(f, A; dims=:, init=Base.NoInit())
reduce(f, A; dims=:, [init])
Reduce 2-argument function `f` along dimensions of `A`. `dims` is a vector specifying the
dimensions to reduce, and `init` is the initial value to use in the reductions. For `+`, `*`,
`max` and `min` the `init` argument is optional.
dimensions to reduce, and the keyword argument `init` is the initial value to use in the
reductions. For `+`, `*`, `max` and `min` the `init` argument is optional.
The associativity of the reduction is implementation-dependent; if you need a particular
associativity, e.g. left-to-right, you should write your own loop or consider using
Expand All @@ -315,9 +315,7 @@ julia> reduce(max, a, dims=1)
4 8 12 16
```
"""
reduce(op, A::AbstractArray; dims=:, init=NoInit()) = _reduce_dim(op, init, A, dims)

_reduce_dim(op, init, A, dims) = mapreduce(identity, op, A; dims = dims, init=init)
reduce(op, A::AbstractArray; kw...) = mapreduce(identity, op, A; kw...)

##### Specific reduction functions #####
"""
Expand Down
2 changes: 1 addition & 1 deletion stdlib/OldPkg/src/reqs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function add(lines::Vector{Line}, pkg::AbstractString, versions::VersionSet=Vers
return true
end
length(v) == 1 && v[1] == intersect(v[1],versions) && return copy(lines)
versions = reduce(intersect, versions, v)
versions = reduce(intersect, v; init=versions)
push!(filtered, Requirement(pkg, versions))
end

Expand Down
2 changes: 1 addition & 1 deletion stdlib/Random/src/DSFMT.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function sqrmod!(f::GF2X, m::GF2X)::GF2X
x2i = GF2X(1)
GF2X[copy(mulxmod!(mulxmod!(x2i, m, d+1), m, d+1)) for i=1:d]
end
foldl(GF2X(0), filter(i->coeff(f, i), 0:degree(f))) do g, i
foldl(filter(i->coeff(f, i), 0:degree(f)); init=GF2X(0)) do g, i
i <= d÷2 ? # optimization for "simple" squares
setcoeff!(g, 2i) :
xor!(g, sqrs[i])
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Random/src/RNGs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ copy(src::MersenneTwister) =
r1.idxF == r2.idxF && r1.idxI == r2.idxI

hash(r::MersenneTwister, h::UInt) =
foldr(hash, h, (r.seed, r.state, r.vals, r.ints, r.idxF, r.idxI))
foldr(hash, (r.seed, r.state, r.vals, r.ints, r.idxF, r.idxI); init=h)

function fillcache_zeros!(r::MersenneTwister)
# the use of this function is not strictly necessary, but it makes
Expand Down

0 comments on commit 1a582a3

Please sign in to comment.