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.