Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make multiplication operator (*) behave as short-circuit?

I have lots of computations, specially multiplication, where first part is sometimes zero and I don't want to evaluate second operand in that case. There are at least two short-circuit operators in C#: && and || which evaluate second operand only if necessary. I want to achieve similar behavior with multiplication operator.

In .net you can't overload && operator directly, but you can overload & and false operators, so you can use your extension points to change behavior of short-circuit operator. You can find more details at this article C# operator overloading: the ‘&&’ operator

Is there any means to achieve this or similar behavior for multiplication operator?

This is a pure syntax question, because implementation is very simple. Next method achieves exactly what I want in terms of functionality:

public static double ShortCircuitMultiply(double val, Func<double> anotherValue)
{
    var epsilon = 0.00000001;
    return Math.Abs(val) < epsilon ? 0 : val * anotherValue();
}

Note: this implementation is not full: in C# if you multiply 0.0 with Double.NaN or Double.NegativeInfinity or Double.PositiveInfinity, you'll get NaN, but in terms of ShortCircuitMultiply - only zero. Let's ignore this detail and it's really irrelevant in my domain.

So now if I call it as ShortCircuitMultiply(0.0, longOperation) where longOperation is Func<double>, last term won't be evaluated and result of an operation will be effectively zero.

The problem is, as I already stated, I would have lots of ShortCircuitMultiply calls and I want to make code more readable. I want code to be similar to 0.0 * longOperation() if that is possible.


Another note: I've tried to build wrapper on double and create implicit casting to double and also overload * operator. I understand, that this is probably redundant: I wanted to acheive readability, but trying to build yet another wrapper. Anyway, next code demonstrates my intent:

class MyDouble
{
    double value;
    public MyDouble(double value)
    {
        this.value = value; 
    }

    public static MyDouble operator *(MyDouble left, MyDouble right) 
    {
        Console.WriteLine ("* operator call");
        return new MyDouble(left.value * right.value);
    }

    public static implicit operator double(MyDouble myDouble)
    {
        Console.WriteLine ("cast to double");
        return myDouble.value;
    }

    public static implicit operator MyDouble(double value)
    {
        Console.WriteLine ("cast to MyDouble");
        return new MyDouble(value);
    }
}

Now if I go with:

MyDouble zero = 0;

Console.WriteLine (zero * longOperation()); //longOperation is still Func<double>

I've receive:

cast to MyDouble            
called longOperation        <-- want to avoid this (it's printed from longOperation body)
cast to double             
cast to MyDouble
* operator call
cast to double   
0

But as you can see, longOperation is evaluated long before overloaded operator is called, and I can't substitute one of the parameters with Func or Expression to make it lazy.

like image 988
Ilya Ivanov Avatar asked May 04 '13 14:05

Ilya Ivanov


3 Answers

There is no way to easily do what you want. The C# language is a very "eager" language in that it always evaluates operands before it runs operators, even when as you note, you could possibly skip one by knowing the other. The only exceptions are ? :, and its equivalents, &&, || and ??. (All of which can be reduced to ? :.)

As you correctly note, you can attain laziness through use of a lambda; a Func<T> represents a T that will be computed on demand. But as you also correctly note, the syntax for doing so is rather heavyweight.

Consider writing your program in Haskell if you must have lazy arithmetic. It's very lazy, and I gather it is very easy to define your own operator semantics. F# is also an option and is probably easier to learn for the C# programmer.

like image 121
Eric Lippert Avatar answered Sep 28 '22 21:09

Eric Lippert


The problem with your MyDouble wrapper class is that you use it by calling longOperation directly. As * is not short circuiting, it will be called directly.

Instead, you could just make your wrapper accept a Func<double> as the second parameter instead of the double value itself. So it would work like the ShortCircuitMultiply function:

public static MyDouble operator *(MyDouble left, Func<double> right)
{
    return Math.Abs(left.value) < epsilon ? new MyDouble(0) : new MyDouble(left.value * right());
}

Then you would use it like this:

MyDouble x = 0;
Console.WriteLine(x * LongOperation);

And even chaining works:

MyDouble x = 5;
Console.WriteLine(x * OperationReturingZero * LongOperation);

Full example

class Program
{
    static void Main()
    {
        MyDouble x = 0;
        Console.WriteLine(x * LongOperation);

        MyDouble y = 5;
        Console.WriteLine(y * OperationReturningZero * LongOperation);

        Console.ReadLine();
    }

    private static double LongOperation()
    {
        Console.WriteLine("LongOperation");
        return 5;
    }

    private static double OperationReturningZero()
    {
        Console.WriteLine("OperationReturningZero");
        return 0;
    }
}

class MyDouble
{
    private static double epsilon = 0.00000001;
    private double value;

    public MyDouble(double value)
    {
        this.value = value;
    }

    public static MyDouble operator *(MyDouble left, Func<double> right)
    {
        Console.WriteLine("* (MyDouble, Func<double>)");
        return Math.Abs(left.value) < epsilon ? new MyDouble(0) : new MyDouble(left.value * right());
    }

    public static MyDouble operator *(MyDouble left, MyDouble right)
    {
        Console.WriteLine("* (MyDouble, MyDouble)");
        return new MyDouble(left.value * right.value);
    }

    public static implicit operator double(MyDouble myDouble)
    {
        Console.WriteLine("cast to double");
        return myDouble.value;
    }

    public static implicit operator MyDouble(double value)
    {
        Console.WriteLine("cast to MyDouble");
        return new MyDouble(value);
    }
}

Output:

cast to MyDouble
* (MyDouble, Func<double>)
cast to double
0
cast to MyDouble
* (MyDouble, Func<double>)
OperationReturningZero
* (MyDouble, Func<double>)
cast to double
0
like image 29
poke Avatar answered Sep 28 '22 21:09

poke


Well you could write an extension method for double, but I'm not sure if it's really what you're looking for.

You could then have code like this:

double z = someNumberThatMightBeZero();
double r = z.Times(number);

where number is a method returning a double.

using System;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            double z = zero();
            double r = z.Times(number);
            Console.WriteLine(r);
        }

        static double zero()
        {
            return 0;
        }

        static double number()
        {
            Console.WriteLine("in number()");
            return 100;
        }
    }

    public static class DoubleExt
    {
        public static double Times(this double val, Func<double> anotherValue)
        {
            const double epsilon = 0.00000001;
            return Math.Abs(val) < epsilon ? 0 : val * anotherValue();
        }
    }
}
like image 44
Matthew Watson Avatar answered Sep 28 '22 22:09

Matthew Watson