Wednesday, August 09, 2006

Operator overloading in ruby

Most operators in ruby (e.g. +, -, *, /, % etc) are actually method calls, and they can be overloaded just like other method calls. But unlike C++, Ruby does not have operators like +=, -=, *=, /= etc, so a += 1 is translated directly to a = a + 1.

This involves some performance penalty in some cases, for example:


a1 = [1, 2, 3]
a2 = [4, 5, 6]
a1 += a2


Behind the scenes, a new array is created (as a1 += a2 is equivalent to a1 = a1 + a2, operator + will create a new array, then a1 is assigned to hold the reference to the new array, and the old a1 will be garbage collected). If you just want to append a2 to a1, the following code is a little bit more efficient:


a1.concat(a2)


concat method will directly update the content of a1 without creating a new array.

And it is surprising to know that not all ruby's operators are method calls, so you can not overload !, not, &&, and, ||, or.

UPDATE 09/12/2006: Chris pointed out an error in my original article(I shouldn't use << operator as the alternative of +=), see comments for details. Thanks, Chris!

Reference:
[1]Are +, -, * ... operators?

1 Comments:

Anonymous Chris said...

It should be noted that although a1<<a2 is faster than a1+=a2, they don't do the same thing. Ob-ser-uve!

>> a1 = [1,2,3]; a2 = [4,5,6]; a1 += a2
=> [1, 2, 3, 4, 5, 6]
>> a1 = [1,2,3]; a2 = [4,5,6]; a1 << a2
=> [1, 2, 3, [4, 5, 6]]

The << operator puts a2 inside a1. If you want it to be a regular list, you'd then have to .flatten it (which is going to create another list).

The fastest to stick one list onto the end of another is probably a1.concat( a2 ).

11:48 AM  

Post a Comment

<< Home