Skip to content

Commit

Permalink
Move v0 to an init keyword argument for reduce, etc
Browse files Browse the repository at this point in the history
The initial value `v0` has been moved to a keyword argument `init` in
`reduce`, `mapreduce`, `foldl`, `mapfoldl`, `foldr` and `mapfoldr`.

(This will allow the future addition of multiple input iterators like
we allow for `map`).
  • Loading branch information
Andy Ferris committed Jun 22, 2018
1 parent 748f008 commit 96dda6f
Show file tree
Hide file tree
Showing 18 changed files with 136 additions and 176 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,10 @@ Library improvements
* Added an optimized method of `vecdot` for taking the Frobenius inner product
of sparse matrices. ([#27470])

* The initial element `v0` in `reduce(op, v0, itr)` has been replaced with an `init`
optional keyword argument, as in `reduce(op, itr; init=v0)`. Similarly for `foldl`,
`foldr`, `mapreduce`, `mapfoldl` and `mapfoldr`. ([#27711])

Compiler/Runtime improvements
-----------------------------

Expand Down
2 changes: 1 addition & 1 deletion base/Enums.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function membershiptest(expr, values)
if length(values) == hi - lo + 1
:($lo <= $expr <= $hi)
elseif length(values) < 20
foldl((x1,x2)->:($x1 || ($expr == $x2)), :($expr == $(values[1])), values[2:end])
foldl((x1,x2)->:($x1 || ($expr == $x2)), values[2:end]; init = :($expr == $(values[1])))
else
:($expr in $(Set(values)))
end
Expand Down
10 changes: 5 additions & 5 deletions base/abstractset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ julia> a
Set([7, 4, 3, 5, 1])
```
"""
union!(s::AbstractSet, sets...) = foldl(union!, s, sets)
union!(s::AbstractSet, sets...) = foldl(union!, sets; init = s)

max_values(::Type) = typemax(Int)
max_values(T::Type{<:Union{Nothing,BitIntegerSmall}}) = 1 << (8*sizeof(T))
Expand Down Expand Up @@ -109,7 +109,7 @@ const ∩ = intersect
Intersect all passed in sets and overwrite `s` with the result.
Maintain order with arrays.
"""
intersect!(s::AbstractSet, itrs...) = foldl(intersect!, s, itrs)
intersect!(s::AbstractSet, itrs...) = foldl(intersect!, itrs; init = s)
intersect!(s::AbstractSet, s2::AbstractSet) = filter!(_in(s2), s)
intersect!(s::AbstractSet, itr) =
intersect!(s, union!(emptymutable(s, eltype(itr)), itr))
Expand Down Expand Up @@ -147,8 +147,8 @@ julia> a
Set([4])
```
"""
setdiff!(s::AbstractSet, itrs...) = foldl(setdiff!, s, itrs)
setdiff!(s::AbstractSet, itr) = foldl(delete!, s, itr)
setdiff!(s::AbstractSet, itrs...) = foldl(setdiff!, itrs; init = s)
setdiff!(s::AbstractSet, itr) = foldl(delete!, itr; init = s)


"""
Expand Down Expand Up @@ -185,7 +185,7 @@ Construct the symmetric difference of the passed in sets, and overwrite `s` with
When `s` is an array, the order is maintained.
Note that in this case the multiplicity of elements matters.
"""
symdiff!(s::AbstractSet, itrs...) = foldl(symdiff!, s, itrs)
symdiff!(s::AbstractSet, itrs...) = foldl(symdiff!, itrs; init = s)

function symdiff!(s::AbstractSet, itr)
for x in itr
Expand Down
2 changes: 1 addition & 1 deletion base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2366,7 +2366,7 @@ _shrink_filter!(keep) = _unique_filter!(∈, pop!, keep)

function _grow!(pred!, v::AbstractVector, itrs)
filter!(pred!, v) # uniquify v
foldl(v, itrs) do v, itr
foldl(itrs; init = v) do v, itr
mapfilter(pred!, push!, itr, v)
end
end
Expand Down
6 changes: 3 additions & 3 deletions base/bitset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ very large integers), use [`Set`](@ref) instead.
BitSet(itr) = union!(BitSet(), itr)

# Special implementation for BitSet, which lacks a fast `length` method.
union!(s::BitSet, itr) = foldl(push!, s, itr)
union!(s::BitSet, itr) = foldl(push!, itr; init = s)

@inline intoffset(s::BitSet) = s.offset << 6

Expand Down Expand Up @@ -274,7 +274,7 @@ intersect!(s1::BitSet, s2::BitSet) = _matched_map!(&, s1, s2)

setdiff!(s1::BitSet, s2::BitSet) = _matched_map!((p, q) -> p & ~q, s1, s2)

symdiff!(s::BitSet, ns) = foldl(int_symdiff!, s, ns)
symdiff!(s::BitSet, ns) = foldl(int_symdiff!, ns; init = s)

function int_symdiff!(s::BitSet, n::Integer)
n0 = _check_bitset_bounds(n)
Expand Down Expand Up @@ -309,7 +309,7 @@ function last(s::BitSet)
idx == -1 ? _throw_bitset_notempty_error() : idx + intoffset(s)
end

length(s::BitSet) = bitcount(s.bits) # = mapreduce(count_ones, +, 0, s.bits)
length(s::BitSet) = bitcount(s.bits) # = mapreduce(count_ones, +, s.bits; init = 0)

function show(io::IO, s::BitSet)
print(io, "BitSet([")
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ end

function compute_value_for_block(ir::IRCode, domtree::DomTree, allblocks, du, phinodes, fidx, curblock)
curblock = find_curblock(domtree, allblocks, curblock)
def = reduce(max, 0, stmt for stmt in du.defs if block_for_inst(ir.cfg, stmt) == curblock)
def = reduce(max, stmt for stmt in du.defs if block_for_inst(ir.cfg, stmt) == curblock; init = 0)
def == 0 ? phinodes[curblock] : val_for_def_expr(ir, def, fidx)
end

Expand Down Expand Up @@ -680,7 +680,7 @@ function getfield_elim_pass!(ir::IRCode, domtree)
# not to include any intermediaries that have dead uses. As a result, missing uses will only ever
# show up in the nuses_total count.
nleaves = length(defuse.uses) + length(defuse.defs) + length(defuse.ccall_preserve_uses)
nuses_total = compact.used_ssas[idx] + mapreduce(idx->compact.used_ssas[idx], +, 0, intermediaries) - length(intermediaries)
nuses_total = compact.used_ssas[idx] + mapreduce(idx->compact.used_ssas[idx], +, intermediaries; init = 0) - length(intermediaries)
nleaves == nuses_total || continue
# Find the type for this allocation
defexpr = ir[SSAValue(idx)]
Expand Down
6 changes: 3 additions & 3 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
return rewrap_unionall(unwrapva(s.types[1]), s00)
end
# union together types of all fields
return reduce(tmerge, Bottom, map(t -> rewrap_unionall(unwrapva(t), s00), s.types))
return reduce(tmerge, map(t -> rewrap_unionall(unwrapva(t), s00), s.types); init = Bottom)
end
fld = name.val
if isa(fld,Symbol)
Expand Down Expand Up @@ -688,8 +688,8 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
if !(Int <: name || Symbol <: name)
return Bottom
end
return reduce(tmerge, Bottom,
Any[ fieldtype_tfunc(s0, Const(i)) for i = 1:length(ftypes) ])
return reduce(tmerge, Any[ fieldtype_tfunc(s0, Const(i)) for i = 1:length(ftypes) ];
init = Bottom)
end

fld = name.val
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/typelimits.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function limit_tuple_type_n(@nospecialize(t), lim::Int)
p = t.parameters
n = length(p)
if n > lim
tail = reduce(typejoin, Bottom, Any[p[lim:(n-1)]..., unwrapva(p[n])])
tail = reduce(typejoin, Any[p[lim:(n-1)]..., unwrapva(p[n])]; init = Bottom)
return Tuple{p[1:(lim-1)]..., Vararg{tail}}
end
return t
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/typeutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ _typename(a::DataType) = Const(a.name)
function tuple_tail_elem(@nospecialize(init), ct)
# FIXME: this is broken: it violates subtyping relations and creates invalid types with free typevars
tmerge_maybe_vararg(@nospecialize(a), @nospecialize(b)) = tmerge(a, tvar_extent(unwrapva(b)))
return Vararg{widenconst(foldl(tmerge_maybe_vararg, init, ct))}
return Vararg{widenconst(foldl(tmerge_maybe_vararg, ct; init = init))}
end

function countunionsplit(atypes)
Expand Down
8 changes: 8 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1723,6 +1723,14 @@ end
@deprecate_moved eigs "Arpack"
@deprecate_moved svds "Arpack"

# PR #27711
@deprecate reduce(op, v0, itr) reduce(op, itr; init=v0)
@deprecate foldl(op, v0, itr) foldl(op, itr; init=v0)
@deprecate foldr(op, v0, itr) foldr(op, itr; init=v0)
@deprecate mapreduce(f, op, v0, itr) mapreduce(f, op, itr; init=v0)
@deprecate mapfoldl(f, op, v0, itr) mapfoldl(f, op, itr; init=v0)
@deprecate mapfoldr(f, op, v0, itr) mapfoldr(f, op, itr; init=v0)

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
2 changes: 1 addition & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ function gcdx(a::BigInt, b::BigInt)
g, s, t
end

sum(arr::AbstractArray{BigInt}) = foldl(MPZ.add!, BigInt(0), arr)
sum(arr::AbstractArray{BigInt}) = foldl(MPZ.add!, arr; init = BigInt(0))
# note: a similar implementation for `prod` won't be efficient:
# 1) the time complexity of the allocations is negligible compared to the multiplications
# 2) assuming arr contains similarly sized BigInts, the multiplications are much more
Expand Down
2 changes: 1 addition & 1 deletion base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ lcm(a::Integer, b::Integer) = lcm(promote(a,b)...)
gcd(a::Integer, b::Integer...) = gcd(a, gcd(b...))
lcm(a::Integer, b::Integer...) = lcm(a, lcm(b...))

lcm(abc::AbstractArray{<:Integer}) = reduce(lcm,one(eltype(abc)),abc)
lcm(abc::AbstractArray{<:Integer}) = reduce(lcm, abc; init = one(eltype(abc)))

function gcd(abc::AbstractArray{<:Integer})
a = zero(eltype(abc))
Expand Down
Loading

0 comments on commit 96dda6f

Please sign in to comment.