Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duck type the function in map, reduce, etc. #10312

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,7 @@ end

##
# generic map on any iterator
function map(f, iters...)
function mapc(f, iters...)
result = []
len = length(iters)
states = [start(iters[idx]) for idx in 1:len]
Expand Down Expand Up @@ -1341,8 +1341,8 @@ function map_promote(f, A::AbstractArray)
end

## 1 argument
map!(f, A::AbstractArray) = map!(f, A, A)
function map!(f, dest::AbstractArray, A::AbstractArray)
mapc!(f, A::AbstractArray) = mapc!(f, A, A)
function mapc!(f, dest::AbstractArray, A::AbstractArray)
for i = 1:length(A)
dest[i] = f(A[i])
end
Expand All @@ -1368,7 +1368,7 @@ function map_to!{T}(f, offs, dest::AbstractArray{T}, A::AbstractArray)
return dest
end

function map(f, A::AbstractArray)
function mapc(f, A::AbstractArray)
if isempty(A); return similar(A); end
first = f(A[1])
dest = similar(A, typeof(first))
Expand All @@ -1377,7 +1377,7 @@ function map(f, A::AbstractArray)
end

## 2 argument
function map!(f, dest::AbstractArray, A::AbstractArray, B::AbstractArray)
function mapc!(f, dest::AbstractArray, A::AbstractArray, B::AbstractArray)
for i = 1:length(A)
dest[i] = f(A[i], B[i])
end
Expand All @@ -1400,7 +1400,7 @@ function map_to!{T}(f, offs, dest::AbstractArray{T}, A::AbstractArray, B::Abstra
return dest
end

function map(f, A::AbstractArray, B::AbstractArray)
function mapc(f, A::AbstractArray, B::AbstractArray)
shp = promote_shape(size(A),size(B))
if prod(shp) == 0
return similar(A, promote_type(eltype(A),eltype(B)), shp)
Expand All @@ -1412,7 +1412,7 @@ function map(f, A::AbstractArray, B::AbstractArray)
end

## N argument
function map!(f, dest::AbstractArray, As::AbstractArray...)
function mapc!(f, dest::AbstractArray, As::AbstractArray...)
n = length(As[1])
i = 1
ith = a->a[i]
Expand Down Expand Up @@ -1440,7 +1440,7 @@ function map_to!{T}(f, offs, dest::AbstractArray{T}, As::AbstractArray...)
return dest
end

function map(f, As::AbstractArray...)
function mapc(f, As::AbstractArray...)
shape = mapreduce(size, promote_shape, As)
if prod(shape) == 0
return similar(As[1], promote_eltype(As...), shape)
Expand Down Expand Up @@ -1499,4 +1499,3 @@ function randsubseq!(S::AbstractArray, A::AbstractArray, p::Real)
end

randsubseq{T}(A::AbstractArray{T}, p::Real) = randsubseq!(T[], A, p)

6 changes: 3 additions & 3 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1298,9 +1298,9 @@ end
## Filter ##

# given a function returning a boolean and an array, return matching elements
filter(f::Function, As::AbstractArray) = As[map(f, As)::AbstractArray{Bool}]
filterc(f, As::AbstractArray) = As[mapc(f, As)::AbstractArray{Bool}]

function filter!(f::Function, a::Vector)
function filterc!(f, a::Vector)
insrt = 1
for curr = 1:length(a)
if f(a[curr])
Expand All @@ -1312,7 +1312,7 @@ function filter!(f::Function, a::Vector)
return a
end

function filter(f::Function, a::Vector)
function filterc(f, a::Vector)
r = Array(eltype(a), 0)
for i = 1:length(a)
if f(a[i])
Expand Down
24 changes: 23 additions & 1 deletion base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,29 @@ function length_checked_equal(args...)
n
end

map(f::Callable, a::Array{Any,1}) = Any[ f(a[i]) for i=1:length(a) ]
# Ambiguity resolution for map and friends. Most methods in Base use
# the "c" (container) variant, and dispatch only on the container
# type. Use map directly when you want to dispatch on f.
map(f) = f()
map(f, itr) = mapc(f, itr)
map(f, itrA, itrB) = mapc(f, itrA, itrB)
map(f, itr...) = mapc(f, itr...)
map!(f, itr) = mapc!(f, itr)
map!(f, dest, src) = mapc!(f, dest, src)
map!(f, dest, src...) = mapc!(f, dest, src...)
filter(f, itr) = filterc(f, itr)
filter!(f, itr) = filterc!(f, itr)
mapreduce(f, op, itr) = mapreducec(f, op, itr)
mapreduce(f, op, v0, itr) = mapreducec(f, op, v0, itr)
mapfoldl(f, op, itr) = mapfoldlc(f, op, itr)
mapfoldr(f, op, itr) = mapfoldrc(f, op, itr)
mapfoldl(f, op, v0, itr) = mapfoldlc(f, op, v0, itr)
mapfoldr(f, op, v0, itr) = mapfoldrc(f, op, v0, itr)
reduce(op, itr) = reducec(op, itr)
reduce(op, v0, itr) = reducec(op, v0, itr)

mapc(f) = f()
mapc(f, a::Array{Any,1}) = Any[ f(a[i]) for i=1:length(a) ]

macro thunk(ex); :(()->$(esc(ex))); end
macro L_str(s); s; end
Expand Down
4 changes: 2 additions & 2 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1579,7 +1579,7 @@ map(f::Callable, A::BitArray, B::BitArray) = map(specialized_bitwise_binary(f),
map(f::BitFunctorUnary, A::BitArray) = map!(f, similar(A), A)
map(f::BitFunctorBinary, A::BitArray, B::BitArray) = map!(f, similar(A), A, B)

map!(f::Callable, A::BitArray) = map!(f, A, A)
mapc!(f, A::BitArray) = mapc!(f, A, A)
map!(f::Callable, dest::BitArray, A::BitArray) = map!(specialized_bitwise_unary(f), dest, A)
map!(f::Callable, dest::BitArray, A::BitArray, B::BitArray) = map!(specialized_bitwise_binary(f), dest, A, B)

Expand Down Expand Up @@ -1607,7 +1607,7 @@ end

## Filter ##

function filter(f::Function, Bs::BitArray)
function filterc(f, Bs::BitArray)
boolmap::Array{Bool} = map(f, Bs)
Bs[boolmap]
end
Expand Down
10 changes: 5 additions & 5 deletions base/darray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -318,17 +318,17 @@ end

## higher-order functions ##

map(f::Callable, d::DArray) = DArray(I->map(f, localpart(d)), d)
mapc(f, d::DArray) = DArray(I->mapc(f, localpart(d)), d)

reduce(f::Function, d::DArray) =
mapreduce(fetch, f,
reducec(f, d::DArray) =
mapreducec(fetch, f,
Any[ @spawnat p reduce(f, localpart(d)) for p in procs(d) ])

mapreduce(f :: Function, opt :: Function, d :: DArray) =
mapreducec(f, opt, d :: DArray) =
mapreduce(fetch, opt,
Any[ @spawnat p mapreduce(f, opt, localpart(d)) for p in procs(d) ])

function map!(f::Callable, d::DArray)
function mapc!(f, d::DArray)
@sync begin
for p in procs(d)
@spawnat p map!(f, localpart(d))
Expand Down
4 changes: 2 additions & 2 deletions base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -191,15 +191,15 @@ function merge(d::Associative, others::Associative...)
merge!(Dict{K,V}(), d, others...)
end

function filter!(f::Function, d::Associative)
function filterc!(f, d::Associative)
for (k,v) in d
if !f(k,v)
delete!(d,k)
end
end
return d
end
filter(f::Function, d::Associative) = filter!(f,copy(d))
filterc(f, d::Associative) = filterc!(f,copy(d))

eltype{K,V}(::Type{Associative{K,V}}) = (K,V)

Expand Down
6 changes: 3 additions & 3 deletions base/iterator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ done(z::Zip, st) = done(z.a,st[1]) | done(z.z,st[2])

# filter

immutable Filter{I}
flt::Function
immutable Filter{F,I}
flt::F
itr::I
end
filter(flt::Function, itr) = Filter(flt, itr)
filterc(flt, itr) = Filter(flt, itr)

start(f::Filter) = start_filter(f.flt, f.itr)
function start_filter(pred, itr)
Expand Down
2 changes: 1 addition & 1 deletion base/number.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ done(x::Number, state) = state
isempty(x::Number) = false
in(x::Number, y::Number) = x == y

map(f::Callable, x::Number) = f(x)
mapc(f, x::Number) = f(x)

zero(x::Number) = oftype(x,0)
zero{T<:Number}(::Type{T}) = convert(T,0)
Expand Down
22 changes: 11 additions & 11 deletions base/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ function mapfoldl_impl(f, op, v0, itr, i)
end
end

mapfoldl(f, op, v0, itr) = mapfoldl_impl(f, op, v0, itr, start(itr))
mapfoldlc(f, op, v0, itr) = mapfoldl_impl(f, op, v0, itr, start(itr))

mapfoldl(f, op::Function, v0, itr) = mapfoldl_impl(f, specialized_binary(op), v0, itr, start(itr))

function mapfoldl(f, op, itr)
function mapfoldlc(f, op, itr)
i = start(itr)
if done(itr, i)
return Base.mr_empty(f, op, eltype(itr))
Expand Down Expand Up @@ -81,8 +81,8 @@ function mapfoldr_impl(f, op, v0, itr, i::Integer)
end
end

mapfoldr(f, op, v0, itr) = mapfoldr_impl(f, op, v0, itr, endof(itr))
mapfoldr(f, op, itr) = (i = endof(itr); mapfoldr_impl(f, op, f(itr[i]), itr, i-1))
mapfoldrc(f, op, v0, itr) = mapfoldr_impl(f, op, v0, itr, endof(itr))
mapfoldrc(f, op, itr) = (i = endof(itr); mapfoldr_impl(f, op, f(itr[i]), itr, i-1))

foldr(op, v0, itr) = mapfoldr(IdFun(), op, v0, itr)
foldr(op, itr) = mapfoldr(IdFun(), op, itr)
Expand Down Expand Up @@ -112,8 +112,8 @@ function mapreduce_pairwise_impl(f, op, A::AbstractArray, ifirst::Int, ilast::In
end
end

mapreduce(f, op, itr) = mapfoldl(f, op, itr)
mapreduce(f, op, v0, itr) = mapfoldl(f, op, v0, itr)
mapreducec(f, op, itr) = mapfoldlc(f, op, itr)
mapreducec(f, op, v0, itr) = mapfoldlc(f, op, v0, itr)
mapreduce_impl(f, op, A::AbstractArray, ifirst::Int, ilast::Int) =
mapreduce_pairwise_impl(f, op, A, ifirst, ilast, 1024)

Expand Down Expand Up @@ -150,14 +150,14 @@ function _mapreduce{T}(f, op, A::AbstractArray{T})
end
end

mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, A)
mapreduce(f, op, a::Number) = f(a)
mapreducec(f, op, A::AbstractArray) = _mapreduce(f, op, A)
mapreducec(f, op, a::Number) = f(a)

mapreduce(f, op::Function, A::AbstractArray) = _mapreduce(f, specialized_binary(op), A)

reduce(op, v0, itr) = mapreduce(IdFun(), op, v0, itr)
reduce(op, itr) = mapreduce(IdFun(), op, itr)
reduce(op, a::Number) = a
reducec(op, v0, itr) = mapreducec(IdFun(), op, v0, itr)
reducec(op, itr) = mapreducec(IdFun(), op, itr)
reducec(op, a::Number) = a


###### Specific reduction functions ######
Expand Down
8 changes: 4 additions & 4 deletions base/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,11 @@ eachmatch(re::Regex, str::AbstractString) = RegexMatchIterator(re,str)

# miscellaneous methods that depend on Regex being defined

filter!(r::Regex, v) = filter!(x->ismatch(r,x), v)
filter(r::Regex, v) = filter(x->ismatch(r,x), v)
filter!(r::Regex, v) = filterc!(x->ismatch(r,x), v)
filter(r::Regex, v) = filterc(x->ismatch(r,x), v)

filter!(r::Regex, d::Dict) = filter!((k,v)->ismatch(r,k),d)
filter(r::Regex, d::Dict) = filter!(r,copy(d))
filter!(r::Regex, d::Dict) = filterc!((k,v)->ismatch(r,k),d)
filter(r::Regex, d::Dict) = filterc!(r,copy(d))


# Don't serialize the pointers
Expand Down
4 changes: 2 additions & 2 deletions base/set.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ function unique(C)
out
end

function filter(f::Function, s::Set)
function filterc(f, s::Set)
u = similar(s)
for x in s
if f(x)
Expand All @@ -122,7 +122,7 @@ function filter(f::Function, s::Set)
end
return u
end
function filter!(f::Function, s::Set)
function filterc!(f, s::Set)
for x in s
if !f(x)
delete!(s, x)
Expand Down
8 changes: 4 additions & 4 deletions base/sharedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,14 @@ similar(S::SharedArray, T) = similar(S, T, size(S))
similar(S::SharedArray, dims::Dims) = similar(S, eltype(S), dims)
similar(S::SharedArray) = similar(S, eltype(S), size(S))

map(f::Callable, S::SharedArray) = (S2 = similar(S); S2[:] = S[:]; map!(f, S2); S2)
mapc(f, S::SharedArray) = (S2 = similar(S); S2[:] = S[:]; mapc!(f, S2); S2)

reduce(f::Function, S::SharedArray) =
mapreduce(fetch, f,
reducec(f, S::SharedArray) =
mapreducec(fetch, f,
Any[ @spawnat p reduce(f, S.loc_subarr_1d) for p in procs(S) ])


function map!(f::Callable, S::SharedArray)
function mapc!(f, S::SharedArray)
@sync for p in procs(S)
@spawnat p begin
for idx in localindexes(S)
Expand Down
4 changes: 2 additions & 2 deletions base/string.jl
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ end
map_result(s::AbstractString, a::Vector{UInt8}) = UTF8String(a)
map_result(s::Union(ASCIIString,SubString{ASCIIString}), a::Vector{UInt8}) = bytestring(a)

function map(f::Function, s::AbstractString)
function mapc(f, s::AbstractString)
out = IOBuffer(Array(UInt8,endof(s)),true,true)
truncate(out,0)
for c in s
Expand All @@ -834,7 +834,7 @@ function map(f::Function, s::AbstractString)
map_result(s, takebuf_array(out))
end

function filter(f::Function, s::AbstractString)
function filterc(f, s::AbstractString)
out = IOBuffer(Array(UInt8,endof(s)),true,true)
truncate(out,0)
for c in s
Expand Down
24 changes: 11 additions & 13 deletions base/tuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,24 @@ ntuple(f::Function, n::Integer) =
n==5 ? (f(1),f(2),f(3),f(4),f(5),) :
tuple(ntuple(n-2,f)..., f(n-1), f(n))

# 0 argument function
map(f::Callable) = f()
# 1 argument function
map(f::Callable, t::()) = ()
map(f::Callable, t::(Any,)) = (f(t[1]),)
map(f::Callable, t::(Any, Any)) = (f(t[1]), f(t[2]))
map(f::Callable, t::(Any, Any, Any)) = (f(t[1]), f(t[2]), f(t[3]))
map(f::Callable, t::Tuple) = tuple(f(t[1]), map(f,tail(t))...)
mapc(f, t::()) = ()
mapc(f, t::(Any,)) = (f(t[1]),)
mapc(f, t::(Any, Any)) = (f(t[1]), f(t[2]))
mapc(f, t::(Any, Any, Any)) = (f(t[1]), f(t[2]), f(t[3]))
mapc(f, t::Tuple) = tuple(f(t[1]), mapc(f,tail(t))...)
# 2 argument function
map(f::Callable, t::(), s::()) = ()
map(f::Callable, t::(Any,), s::(Any,)) = (f(t[1],s[1]),)
map(f::Callable, t::(Any,Any), s::(Any,Any)) = (f(t[1],s[1]), f(t[2],s[2]))
mapc(f, t::(), s::()) = ()
mapc(f, t::(Any,), s::(Any,)) = (f(t[1],s[1]),)
mapc(f, t::(Any,Any), s::(Any,Any)) = (f(t[1],s[1]), f(t[2],s[2]))
# n argument function
heads() = ()
heads(t::Tuple, ts::Tuple...) = tuple(t[1], heads(ts...)...)
tails() = ()
tails(t::Tuple, ts::Tuple...) = tuple(tail(t), tails(ts...)...)
map(f::Callable, ::(), ts::Tuple...) = ()
map(f::Callable, ts::Tuple...) =
tuple(f(heads(ts...)...), map(f, tails(ts...)...)...)
mapc(f, ::(), ts::Tuple...) = ()
mapc(f, ts::Tuple...) =
tuple(f(heads(ts...)...), mapc(f, tails(ts...)...)...)

## comparison ##

Expand Down
2 changes: 1 addition & 1 deletion base/utf32.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function utf32(p::Union(Ptr{Char}, Ptr{UInt32}, Ptr{Int32}))
utf32(p, len)
end

function map(f::Function, s::UTF32String)
function mapc(f, s::UTF32String)
d = s.data
out = similar(d)
out[end] = char(0)
Expand Down
2 changes: 1 addition & 1 deletion test/parallel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ map!(x->1, d)
# Test mapreduce on DArrays
begin
# Test that the proper method exists on DArrays
sig = methods(mapreduce, (Function, Function, DArray))[1].sig
sig = methods(Base.mapreducec, (Any, Any, DArray))[1].sig
@test sig[3] == DArray

# Test that it is functionally equivalent to the standard method
Expand Down