Operator overloading

For me it is important to write short, easy to read and easy to understand code. When you write a piece of code and see it after a couple of months or even years the meaning should be clear in an instant. One way to achieve brevity in programming is the use of operator overloading. With this it is possible to change the meaning of an operator.

In this example I’ll take two interpreted languages I use (Python and PHP) and show how those languages differ in the support for operator overloading and why Python has a more elegant solution to this problem.

When you have two “List” objects in PHP it would be nice to just add thoses lists to get a third list that contains the contents of both $l1 and $l2.

class Largelist {
}

$l1 = new Largelist();
$l2 = new Largelist();

$l3 = $l1 + $l2;

But unfortunatly this example below will not work in PHP because the ‘+’ operator is only defined for adding numbers (int and float). Adding two objects will cause a notice “Notice: Object of class Largelist could not be converted to int”. PHP tries to cast everything it finds as operands of the ‘+’ operator to a number.

The only solution in PHP is to add a method that implements the addition of two objects and manually call that method.

class Largelist {
   public function add(other) {
   }
}

$l1 = new Largelist();
$l2 = new Largelist();

$l3 = $l1->add($l2);

But this is a lot longer and less elegant to use and understand. For the ‘+’ operator we seem to feel that it should be associative. This means that a + b = b + a, this goes for numbers so it should also go for objects. Even matrix addition is associative. When using the explicit method add this is less clear. Does $l1->add($l2) == $l2->add($l1)?

In Python this works different because the Python compiler will search for the method __add__ in the class when the ‘+’ operator is used. The class can now implement it’s own method for adding two objects.

class Largelist():
    def __add__(self, other):
        pass

l1 = Largelist()
l2 = Largelist()

l3 = l1 + l2

This is a lot more elegant and there can be no doubt about the associativity of the operator. Even complex constructions look more elegant and the operator precedence is more clear because it follows the default rules for the language.
So l4 = l3 - l2 + l1 looks a more clear than l4 = l3.__add__(l2.__sub__(l1)), also there are more parentheses and the method calls are nested.

In numpy this is used for adding, multiplying etc. an matrix.

About semantics..

In Python the + operator on two lists will concatenate those 2 lists to one new list containing the elements from both lists.

>>> [1,2,3,4] + [5,6,7,8]
[1, 2, 3, 4, 5, 6, 7, 8]

PHP on the other hand sees the + operator as a union of both lists. Only the elements from the second list that are in the first list will be put in the resulting list. The result is pretty counterintuitive, so beware if you use this in PHP.

$res = [1,2,3,4] + [5,6,7,8];
print_r($res);
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
)

Debates

I’ve had several debates about operator overloading and not everyone is convinced it should be used. I think it is a good way of writing less and more expressive code but it should not be overdone. And the meaning should be intuitive. You should not change the meaning of an operator in a strange way. ‘+’ should not behave like a substraction for example. With this in mind I think it could be a useful tool.