Oh Ruby, who are you trying to fool?

In every single languages that I know the existence, every arithmetic, bitwise and conditional operators are built-in and global keywords. Well, once again, Ruby had to do things differently. You might be surprised to learn that most ruby operators are not built-in keywords. Fine you’ll tell me… but what are they then?

Instance methods

What? Yes. I’m afraid to tell you that Ruby is trying to fool you badly. The least we could say is that Ruby is a language who took the OO principles very seriously… in some kind of obsessive way (but we like it for this). Let’s look at it concretly :

def do_something_clever
  result = first_number + 18
end

Beware! Ruby is trying to make you believe that “+” is independent from “first_number” and “18”. Meeeeeeeep! (I just tried to reproduce the irratating sound that you hear on a quiz show when some guy gives a wrong answer. Although I admit it sounded more like the road runner on crack) The “+” sign is not a “sign” at all. It is an instance method of our object called “first_number”, which is a Fixnum. And what is 18? 18 is the parameter for the “+” method, of course!
We almost succeed to unmask ruby’s diabolical plans to fool our poor mind, so hold on. If “+” is an instance method of the Fixnum class, then where the hell is the dot between that so called method and our object? Well, that’s where the fooling occurs. For the sake of readability, Ruby lets you write an arithmetic expression the way you’re used to. Then, it does some magic behind the scene. It adds a dot, trims the spaces and somehow manage to transform the arithmetic expression in a standard object method call.
*** Update : Like JC pointed out, it also takes care of operator precedence. So when you write 5+8*5 in IRB (ruby interpreter accessible by command line), it correctly gets tranformed to 5.+((8).*(5)). Note that I don’t know exactly what kind of magic ruby does. I just know for sure that “magic happens somehow” ***
So :

result = first_number + 18

means the following to Ruby :

result = first_number.+(18)

If you really wanted to, you could very well write all your arithmetic expressions the way it is illustrated in the 2nd example, but then people would start hating you and soon you wouldn’t have any friend left. Is this what you want? I don’t think so. Still, I think it’s important to know what’s really happening behind the scene when you write an arithmetic expression.
The same holds true if you use numbers directly in your expression, that is, without storing them in some named objects. In fact, in these cases the name of the object is the number itself. This means that once again, you could have done : result = 5.+(3) and thus taking the unnecessary risk to lose all your friends while living a life of misfortune and pain. Again, that’s not what you want, so I suggest you stick with result = 5 + 3. This last paragraph has been edited on 03/31/2007, thanks to Gary Wright.
Finally, here is how the “+” method declaration looks like :

class Fixnum
  #some implementation
  def +(other)
    #some internal call I am unaware of that does the actual addition
  end
end

As simple as that. All of this gives some strength to the statement : “In ruby, everything is an object”, don’t you think?
#UPDATE 03/29/2007
Thanks to Joseph Wright who brought to my attention that the same thing was possible in smalltalk. I wasn’t aware.
[talking about smalltalk…]
When you define a method, it can either be infix (also called binary), which allows for e.g. ‘5 + 5′, where ‘+’ is the method; unary, which has just one argument, or keyword, which looks like ‘methodName Arg1: Arg2:’
[end quote]

11 thoughts on “Oh Ruby, who are you trying to fool?

  1. I don’t think this is entirely true.
    When you run: “5*8+5” in IRB, it correctly returns 45. If what you say is true, it would be the equivalent of: 5.*(8.+(5)). The inner method would be called first, returning 13, and the outer method would evaluate to 13*5=65.
    So there must be some ruby language magic doing the order of operation rules.

  2. jc,
    5*8+5 is the same as 5.*(8).+(5) which also correctly gives 45 in IRB.
    But I understand what you mean. It’s true that ruby must check for the precedence of operators to correctly evaluate an arithmetic expression. So when you write : 5+8*5 , it gets transformed to 5.+((8).*(5)) instead of 5.+(8).*(5)

  3. There’s a slightly more well-known example for this: the assignment operator. In Ruby, attributes are *always* private; there is *no way* to access them from the outside. (Well, I suppose you can do some meta-programming or eval’ing.) “But wait!”, I here you say, “I *can* do something like ‘foo.bar = 42’, can’t I?”. Yes, you can, but(!) that’s not an assignment (cue Henri Matisse pipe here), it’s a message send. Ruby sneakily transforms
    foo.bar = 42
    into
    foo.bar=(42)
    (Note: the equals sign is part of the message name, just like a question mark or exclamation point.)
    jwm

  4. > …In every single languages that I know the existence,
    > every arithmetic, bitwise and conditional operators
    > are built-in and global keywords.
    You should learn more languages then. Smalltalk, which Ruby copies in many ways, does the same thing, treating *everything* as an object. When you define a method, it can either be infix (also called binary), which allows for e.g. ‘5 + 5’, where ‘+’ is the method; unary, which has just one argument, or keyword, which looks like ‘methodName Arg1: Arg2:’, which you might call like ‘methodName Arg1: [ code block for example] Arg2: otherarg’. I don’t know how Ruby implements this, I think there is some magic that goes on inside, like you say.
    On a related note, in the “Bring your methods to life with punctuation” post, you say:
    > I think ruby is the only language that allows a
    > programmer to name his method logged? for example.
    Not at all. Common Lisp and Scheme allow quite a few different characters, Haskell allows ‘ in its variable names, and I’m sure there are others, though none of them spring immediately to mind.

  5. This would be more impressive, if the method declaration would have some way of specifying operator precedence. As it stands, it’s bizarre, it’s consistent because the operators are really methods but they are treated as a special case … well because they have to be.
    Is there some type of well documented language spec for Ruby were these things are clearly specified (operator precedence?)

  6. Jörg,
    It’s funny because what you are talking about is exactly the subject of my next article. It’s all written already. I just have to publish it tonight. I hope you’ll enjoy it. I would really appreciate your comments on it.
    Augusto, That’s a good question. I really don’t know if there’s some official documentation about that. Anyone knows?

  7. I had actually started cooking up some code examples very similar to yours but figured they would be unreadable in the comments section anyway, without that nice syntax highlighting. Saved me some duplicate work (-;
    jwm

  8. Jörg, yeah it would have been nice if the syntax highlighter was active in the comments as well. (it might had been a little heavy on javascript though… =) )
    Joseph, thanks for the info about smalltalk having the same possibility. I have updated the original post.

  9. It is a tradition that has followed Christmas for
    years and years. 01 seconds and kick out, while the other security
    center “warning. It truly is tough as a way to feel energy required genuine simple fact not having super-hero pics, diverse types of typography, needs besides as a result execute putting together your current reduce.

  10. But, once you nail it, photographing your items will be a quick and painless task.
    Only exceptional photographs help you show your effort and dedication for the globe.
    The most popular paints are made by Marshall’s and are created specifically for use on photographs.

Leave a Reply to Frank Cancel reply

Your email address will not be published. Required fields are marked *