Is this a toy reduction of a concept that you want to apply in a much more
complex way?

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.
>
> 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