Ruby’s Operator Expressions and Message Expressions using Operator Methods Yield Different Results

By Koen

In pure object-oriented languages, such as Smalltalk, numerical and boolean expressions are expressed as message expressions. Non-pure object-oriented languages typically provide operators like +, -, *, /, &&, || to write numerical and boolean expressions, and they have precedence rules for operators, so that a numerical expression has the same semantics as in mathematics.

Interestingly, Ruby includes operators and some of them are implemented as methods, so-called operator methods. Let’s try some examples.

irb(main):001:0> 3 + 4 * 6
=> 27

That is what we expect. It shows that Ruby implements operator precedence. * has precedence over +.

* and + are implemented as operator methods. The pickaxe book states that: “If the operator in an operator expression corresponds to a redefinable method, Ruby will execute the operator expression expr1 operator expr2 as if it had been written (expr1).operator(expr2).” This means that the previous example can also be written as:

irb(main):002:0> 3.+(4).*(6)
=> 42

The result is what we expect. Messages are sent from left to right in an expression like this. The precedence rules do not apply when using the message passing form.

But according to the book, the two forms should yield the same result. They don’t.

Classes can implement operator methods as well, as shown in this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Number
  def initialize(initialValue = 0)
    @value = initialValue
  end
  def  value
    @value
  end
  def +(other)
    self.class.new(self.value + other.value)
  end
  def *(other)
    self.class.new(self.value * other.value)
  end
end

Let’s try some expressions:

irb(main):003:0> (Number.new(3) + Number.new(4) * Number.new(6)).value
=> 27

This is consistent the precedence rules of the operators. When this expression is rewritten with messages, this is the result:

irb(main):004:0> Number.new(3).+(Number.new(4)).*(Number.new(6)).value
=> 42

Again, this shows that the precedence rules do not apply.

Although I expect that, consistent with other object-oriented languages, no precedence rules apply when messages are sent in sequence, Ruby states that using the operator form and the message passing form should be equivalent, but they clearly are not. That is very confusing and error-prone.

Share This

One Response to “Ruby’s Operator Expressions and Message Expressions using Operator Methods Yield Different Results”

  1. Franklyn Mangine Says:

    I like this web site its a master peace ! Glad I discovered this on google. “Observe your enemies, for they first find out your faults.” by Antisthenes.

Leave a Reply