I really like the fact that Ruby has operator overloading. In many cases this feature is not very fitting in a language, but in Ruby it definitely has its place. So what’s the difference? Why do people generally say that operator overloading in C++ is a bad thing, and that Java shouldn’t have it? I believe the main reason is static typing. When you have static typing and combine that with a verbose language, operator overloading doesn’t really fit in. You can’t create DSL looking API’s out of the language since the line noise usually make such efforts futile. And then you’re left with only the bad parts of operator overloading.
In Ruby on the other hand, it fits very well. It actually makes sense to be able to redefine and add operators since there are many places where your code can be made much more readable with it. Of course, you always have to be careful and not go over board with it, but when used riht it improves readability to a large degree. A typical example of nice use of overloading is in Hpricot:
doc/:html/:body/:p/:img
Here the division operator have been overloaded to make it possible for you to write XPath like search strings beginning on a parsed Hpricot document.
Another place I really like is in the Ruby core library where the call method is usually overloaded as []. This makes sense if you think about it – in most cases the objects you can call on will take parameters and return a result based on the parameter. This can be mapped quite neatly to an Array or Hash containing values that are returned, and in fact you can imagine swapping out this restricted usage of an Array or Hash to something that you can call things on.
If the [] method is all you used for access, duck typing makes it easy to send in a Proc instead of an Array or Hash.
Another reason using [] can be nice, is since Ruby doesn’t let you override (). If you want to emulate that kind of behavior, [] can act exactly the same if you want it to.
In the Ruby core, the more useful things that implement [] is Array and Hash, of course, UnboundMethod, BoundMethod, Proc and Continuation. This means that you can do something like proc{ puts “hello” }[] if you feel like it.
There are lots of other nice operators to overload in Ruby, though. Some of the better ones are unary + and unary -, all the common arithmetic operators, ||, &&, |, &, <, >, <=, >=, ~, =~, **, ==, === and a few others. The two things missing here is the ! and friends, and (). But of course, adding () wouldn’t really work with the Ruby language. ! on the other hand should be overridable.
So, you should use operator overloading in Ruby, but be careful that it makes sense and actually gives you a good abstraction, not just something “cool”.
9 Comments, Comment or Ping
I agree that operator overloading in Ruby is generally a good thing. However, I think that your contention that the unary not operator (!) should be overridable is a bad thing. Ruby considers all objects except nil and false to be true for the purpose of conditionals. Allowing an object to decide that it is false (if !obj …) but not true would invalidate all sorts of otherwise reasonable logic about objects. The only case for overloading not I can think of is making RSpec a tad more readable.
I rather like the way Scala handles operators; namely that they’re just method calls with a precedence determined by the first and last character. Such a view fits well with everything being an object, and Scala’s type-system allows them to compile very efficiently in the “non-overloaded” case as well.
October 6th, 2007
As far as I know, C# offers operator overloading with quite a success despite its static typing.
October 6th, 2007
The && and || operators are not overloadable, mainly because they provide “short circuit” evaluation that cannot be reproduced with pure method calls.
October 6th, 2007
I’m glad Ruby allows to overwrite the == operator, in Java I’m always in danger to write s == “bla” when I
mean equals.
Python allows you to overwrite the () operator, so that in every place where a function is expected, you can also provide a class with the __call__ method, which can be used to track state.
October 6th, 2007
It would be nice if Ruby in new versions supported the following behaviour:
when some object is used as boolean expression (e.g. “if foo then”), call to_b (or to_boolean) on it. This would allow creating special proxy objects that could represent e.g. false expression (for now Ruby considers all non-nil-or-false objects to be true). Default implementation for Object#to_b would be ‘true’, False and Nil classes – ‘false’. That would maintain backwards compatibility.
The other thing, it would be nice if foo( … ) would transform into variable-or-method lookup and then call to value.call( … ). I don’t see a reason why this should be hardcoded.
October 7th, 2007
gucci bag
bean bag
bed in a bag
sleeping bag
bag golf
bag beach
floral arrangement
funeral flower
flower seed
floral arrangement
wild flower meadow
flower blossom
dried flower
pickin wild flower
flower clipart
flower delivery chicago
green card lottery
ga lottery
tennessee lottery
national lottery
lottery result
maryland lottery
ny lottery
michigan lottery
georgia lottery
pa lottery
virginia lottery
texas lottery
nj lottery
ohio lottery
illinois lottery
florida lottery
california lottery
naturalizer shoes
steve madden shoes
puma shoes
rockport shoes
sas shoes
vans shoes
merrell shoes
dansko shoes
prom shoes
moccasins
ecco shoes
new balance
zappos
aldo shoes
bakers shoes
dsw shoes
birkenstock
clarks shoes
October 7th, 2007
cymbalta
augmentin
clonidine
Coreg
biaxin
clindamycin
azithromycin
zyrtec
prozac
risperdal
paxil
mobic
synthroid
lasix
prevacid
ultracet
vicodin
verapamil
valtrex
zantac
adderall
dopamine
singulair
strattera
toprol
topamax
valtrex
amoxicillin
plavix
oxycodone
inderal
nexium
neurontin
skateboarding shoes
work boot
wedge sandal
adidas shoes
rack room shoes
keen shoes
October 7th, 2007
The bit about static typing doesn’t make sense to me as it stands. I’m guessing from the line noise bit you meant to say “explicit typing”?
October 8th, 2007
Funny how you say operator overloading is not useful in statically typed languages, and then go on listing features (Xpath-like operators, function-collection equivalence) that Scala has out of the box.
Scala has some powerful DSL creation abilities, some of which would not be possible without static typing (i.e. user-defined control expressions) in a C-like syntax.
October 8th, 2007
Reply to “Operator Overloading in Ruby”