On Tuesday, September 1, 2015 at 1:08:38 PM UTC, Jeffrey Sarnoff wrote:
>
> import Base:(+),(*),(-)
>
> julia> 2+3+4
> 9
> julia> (+){T<:Integer}(a::T,b::T,c::T) = ((a+b)+c)+1
> julia> 2+3+4
> 10
>
> julia> 2-3-4
> -5
> julia> (+){T<:Integer}(a::T,b::T,c::T) = ((a-b)-c)-1
> julia> 2-3-4
> -5
>
> Are (+),(*) the only ops that can be n-ary specialized?
>
No, it seems not.
> What gives them that ability? Why only those?
>
This here:
(a, b, c, xs...)
the ... part allows for 4-ary and higher. I'm not sure why that is helpful
(maybe just for generality, to make 3-ary work), but I can guess way 3-ary
is useful.
I was curiuos by the question, so I looked up. I like how easy Julia is to
check out stuff like this (and change..) so I did:
edit(+, (Float64, Float64, Float64))
and found:
for (op,F) in ((:+,:(AddFun())), (:*,:(MulFun())), (:&,:(AndFun())),
(:|,:(OrFun())),
(:$,:(XorFun())), (:min,:(ElementwiseMinFun())),
(:max,:(ElementwiseMaxFun())), (:kron,:kron))
@eval begin
# note: these definitions must not cause a dispatch loop when
+(a,b) is
# not defined, and must only try to call 2-argument definitions, so
# that defining +(a,b) is sufficient for full functionality.
($op)(a, b, c, xs...) = afoldl($F, ($op)(($op)(a,b),c), xs...)
# a further concern is that it's easy for a type like (Int,Int...)
# to match many definitions, so we need to keep the number of
# definitions down to avoid losing type information.
end
end
[For one op this would be simpler.. but cool how for redundant stuff, this
makes shorter..]
My guess (probably wrong?), without looking further is that this is to help
use 3-ary floating point instruction MultiplyAdd (a=b*c+a) that is faster
than two instructions and more accurate for floating point. At least I know
Julia has support somehow..
for (op,F) in ((:+,:(AddFun())), (:*,:(MulFun())), (:&,:(AndFun())),
(:|,:(OrFun())),
(:$,:(XorFun())), (:min,:(ElementwiseMinFun())),
(:max,:(ElementwiseMaxFun())), (:kron,:kron))
@eval begin
# note: these definitions must not cause a dispatch loop when
+(a,b) is
# not defined, and must only try to call 2-argument definitions, so
# that defining +(a,b) is sufficient for full functionality.
($op)(a, b, c, xs...) = afoldl($F, ($op)(($op)(a,b),c), xs...)
# a further concern is that it's easy for a type like (Int,Int...)
# to match many definitions, so we need to keep the number of
# definitions down to avoid losing type information.
end
end
julia> edit(-, (Float64, Float64, Float64))
ERROR: no method found for the specified argument types
in which at ./reflection.jl:293
in edit at interactiveutil.jl:58
--
Palli.