On Thu, Jul 2, 2015 at 11:09 AM, Jan Drugowitsch <[email protected]> wrote:
> On Thursday, 2 July 2015 16:55:33 UTC+2, Yichao Yu wrote:
>>
>> On Thu, Jul 2, 2015 at 10:48 AM, Tom Breloff <[email protected]> wrote:
>> > Just curious... is there a reason simply checking for non-zero isn't
>> > enough?
>> > Readability? Performance?
>> >
>> > f(a,b,c) = (Bool(a) ? a * (b + c) : 0.0)
>>
>> I'm guessing he want all code that gets his type automatically gets
>> this behavior? If yes, I don't think there's anyway you can do that.
>> If not, then just writing the branch or having a macro to rewrite that
>> in your own code is probably the best solution.
>
>
> Indeed, the reason why I don't want to check for zeros and ones explicitly
> is that some of these appear in inner loops and would reduce performance.
>
> I already thought of macros as a possible solution, but I was wondering if
> the same could be achieved in a more implicit/elegant way.

Implicit and elegant sometimes conflict with each other =)

If you have control over the code that uses this, using a macro is the
way to go. A function can't possibly do this.

You could have a look at https://github.com/one-more-minute/Lazy.jl though.

>
> Thanks,
> Jan
>
>>
>> > On Thursday, July 2, 2015 at 9:47:59 AM UTC-4, Jan Drugowitsch wrote:
>> >>
>> >> 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

Reply via email to