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

Deprecate functors.jl #15692

Closed
timholy opened this issue Mar 30, 2016 · 7 comments
Closed

Deprecate functors.jl #15692

timholy opened this issue Mar 30, 2016 · 7 comments
Labels
help wanted Indicates that a maintainer wants help on an issue or pull request

Comments

@timholy
Copy link
Sponsor Member

timholy commented Mar 30, 2016

With #13412, it's not obvious to me that we need base/functors.jl anymore. The one trick is that for dispatch you seem to need (EDIT: wrong! see below) to write

@eval foo(::$(typeof(+))) = 1
@eval foo(::$(typeof(*))) = 2

Presuming that the much-admired Guardians Of Julia's Build Time do not object to this plan (due to the need for the @eval), this seems like a good beginner/intermediate get-started-contributing-to-julia project.

@timholy timholy added the help wanted Indicates that a maintainer wants help on an issue or pull request label Mar 30, 2016
@carnaval
Copy link
Contributor

I don't think you'd ever actually need to dispatch on the function itself, except maybe for one is_bitwise trait that asserts that you can do every bit in parallel for the bitarray stuff. It should not change build time since lowering is basically rewriting every function to what functors.jl does manually.

I'd be very happy to see all that go away, and i'm sure I'm not the only one ! :-)

@yuyichao
Copy link
Contributor

Also you don't need eval

julia> foo(::typeof(+)) = 1
foo (generic function with 1 method)

julia> foo(::typeof(*)) = 2
foo (generic function with 2 methods)

julia> foo(+)
1

julia> foo(*)
2

@StefanKarpinski
Copy link
Sponsor Member

Yes, this definitely needs doing. Unless you actually need different behavior for different functions, we don't need the dispatch bit – the compiler now automatically does the specialization that we were previously hand rolling.

@timholy
Copy link
Sponsor Member Author

timholy commented Mar 30, 2016

Oh, nice @yuyichao. So I guess the guardians won't complain 😄.

@StefanKarpinski and @carnaval, agreed that often you don't need to dispatch, but a surprisingly-large fraction of the code that exploits the definitions in functors uses them for traits:

tim@cannon:~/src/julia-0.5/base$ grep -r MulFun *
arraymath.jl:          (:.*,  DotMulFun()),
broadcast.jl:using Base: AddFun, SubFun, MulFun, LDivFun, RDivFun, PowFun
broadcast.jl:eltype_mul(As::AbstractArray...) = promote_eltype_op(MulFun(), As...)
functors.jl:immutable MulFun <: Func{2} end
functors.jl:(::MulFun)(x, y) = x * y
functors.jl:immutable DotMulFun <: Func{2} end
functors.jl:(::DotMulFun)(x, y) = x .* y
functors.jl:    is(f, *) ? MulFun() :
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(), arithtype(T), arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T), arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T), arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T), arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T), arithtype(S))
linalg/matmul.jl:    TS = promote_op(MulFun(),arithtype(T),arithtype(S))
linalg/matmul.jl:Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) = Ac_mul_Bc!(similar(B, promote_op(MulFun(),arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B)
linalg/matmul.jl:    C = similar(B, promote_op(MulFun(),arithtype(T),arithtype(S)), mA, nB)
linalg/matmul.jl:    matmul2x2!(similar(B, promote_op(MulFun(),T,S), 2, 2), tA, tB, A, B)
linalg/matmul.jl:    matmul3x3!(similar(B, promote_op(MulFun(),T,S), 3, 3), tA, tB, A, B)
linalg/diagonal.jl:    scale!(similar(A, promote_op(MulFun(), eltype(A), eltype(D.diag))), A, D.diag)
linalg/diagonal.jl:    scale!(similar(A, promote_op(MulFun(), eltype(A), eltype(D.diag))), D.diag, A)
linalg.jl:using Base: promote_op, MulFun
operators.jl:for (op,F) in ((:+,:(AddFun())), (:*,:(MulFun())), (:&,:(AndFun())), (:|,:(OrFun())),
promotion.jl:#   promote_op{R<:MyType,S<:MyType}(::MulFun, ::Type{R}, ::Type{S}) = MyType{multype(R,S)}
reducedim.jl:for (Op, initfun) in ((:AddFun, :zero), (:MulFun, :one), (:MaxFun, :typemin), (:MinFun, :typemax))
reducedim.jl:function reducedim_init{S}(f, op::MulFun, A::AbstractArray{S}, region)
reducedim.jl:        reducedim_init(f::IdFun, op::MulFun, A::$T, region) =
reducedim.jl:        reducedim_init(f::Union{AbsFun,Abs2Fun}, op::MulFun, A::$T, region) =
reducedim.jl:    is(op, *) ? MulFun() :
reducedim.jl:for (fname, Op) in [(:sum, :AddFun), (:prod, :MulFun),
reduce.jl:r_promote(::MulFun, x::WidenReduceResult) = widen(x)
reduce.jl:r_promote(::MulFun, x::Number) = oftype(x * one(x), x)
reduce.jl:r_promote(::MulFun, x) = x
reduce.jl:mr_empty(::IdFun, op::MulFun, T) = r_promote(op, one(T)::T)
reduce.jl:prod(f::Union{Callable,Func{1}}, a) = mapreduce(f, MulFun(), a)
reduce.jl:prod(a) = mapreduce(IdFun(), MulFun(), a)
sparse/sparsevector.jl:import Base: Func, AddFun, MulFun, MaxFun, MinFun, SubFun, sort
sparse/sparsevector.jl:                         (:_vmul, :MulFun, 0)]
sparse/sparsevector.jl:    _At_or_Ac_mul_B!(MulFun(), α, A, x, β, y)
sparse/sparsevector.jl:    _At_or_Ac_mul_B(MulFun(), A, x)
sparse/sparsematrix.jl:(.*)(A::AbstractArray, B::AbstractArray) = broadcast_zpreserving(MulFun(), A, B)
sparse/sparsematrix.jl:# Specialized mapreduce for AddFun/MulFun
sparse/sparsematrix.jl:_mapreducezeros(f, ::Base.MulFun, T::Type, nzeros::Int, v0) =
sparse/sparsematrix.jl:function Base._mapreduce{T}(f, op::Base.MulFun, A::SparseMatrixCSC{T})

Any case of ::MulFun would need to be dispatched on typeof(*).

@vtjnash
Copy link
Sponsor Member

vtjnash commented Mar 30, 2016

As an quick initial / deprecation pass, i think we could try defining const MulFun = typeof(*), and then see how much can just go away since it is just re-dispatching between those two.

@timholy
Copy link
Sponsor Member Author

timholy commented Mar 30, 2016

That seemingly won't work as a substitute for Base.MulFun().

julia> const MF = typeof(*)
Base.#*

julia> MF()
ERROR: MethodError: no method matching Base.#*()
 in eval(::Module, ::Any) at ./boot.jl:237

@KristofferC
Copy link
Sponsor Member

julia> call(::Type{typeof(+)}) = +

julia> typeof(+)()(1,2)
3

julia> const AF = typeof(+)
Base.#+

julia> AF()(1,2)
3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Indicates that a maintainer wants help on an issue or pull request
Projects
None yet
Development

No branches or pull requests

7 participants