Dear Julia users,
I am implementing an algorithm to solve a specific type of Volterra
integral equation, and that simplifies significantly if some of its
parameters are set to zero or one. The function implementing the algorithm
takes quite a few arguments, such that writing specific versions for
different arguments being zero/one would lead to too many different
functions, which I would like to avoid. What I would rather like to do is
to write one generic function and let the compiler prune different parts of
the function, depending on the argument types.
A minimal example of what I would like to do is
immutable Zero <: Number; end
const _zero = Zero()
Base.promote_rule{T<:Number}(::Type{Zero}, ::Type{T}) = T
Base.convert{T<:Number}(::Type{T}, ::Zero) = zero(T)
*(::Zero, ::Zero) = _zero
*(::Zero, ::Bool) = _zero
*(::Bool, ::Zero) = _zero
*(::Zero, ::Number) = _zero
*(::Number, ::Zero) = _zero
f(a, b, c) = a * (println("summing b + c"); b + c)
println("Evaluating f(0, 1, 2)")
f(0, 1, 2)
println("Evaluating f(_zero, 1, 2)")
f(_zero, 1, 2)
(with Zero defined similar
to https://groups.google.com/forum/#!topic/julia-users/0ab30bE8q6c)
Running the above results in
Evaluating f(0, 1, 2)
summing b + c
Evaluating f(_zero, 1, 2)
summing b + c
even though the result of the second "summing b + c" is discarded, and
therefore wouldn't need to be evaluated. This is no surprise, as *(.,.) is
a standard function that evaluates its operands before applying the
function. Is there any way to change this behavior and turn *(.,.) into a
function that performs short-circuit evaluation? If not, is there an
alternative approach that achieves this without writing tons of specialized
functions?
Thanks,
Jan