
4 interesting examples using operator precedence in Ruby
In this article, we’re going to explore the following topics:
method 'arg' and return
method1 || method2 'hello'
variable = a or b
block {..}
vsblock do..end
Introduction
Operator precedence is a collection of rules that reflect conventions about which procedures to perform first in order to evaluate a given mathematical expression
It’s a very important layer of any programming language. It can definitely change the way of using a language.
In effect, depending on the priority given to a specific operator, keyword or method call, your program can produce unattended side effects.
In this article, we’re going to detail some idiom that can ease the readability of you code but can also lead to some undesirable side effects in Ruby.
method 'arg'
and return
This idiom can ends up to an unattended side effect as the &&
operator has a higher precedence than the and
one
produces
"method1"
Here only the call to method1
calls the p
method.
Why the call to method2
doesn’t output "method2"
?
This is due to the fact that &&
has a higher precedence than the method2
method call when and
has a lower one.
Let’s slightly modify the above example to show you how Ruby executes the content of method1
and method2
I added parens to show you how Ruby processes operations in the first example.
We can see that for method1
, the and
operator has a lower precedence than a method call (p 'method1'
in our case).
So the method call is processed then return
is called.
For method2
the &&
operator has a higher precedence than the p ‘method2'
method call.
So because there is no parens around the parameter of the p
method call then the &&
operator will apply a LOGICAL AND
operation between ‘method2'
and return
first.
Then the result of this operation will be passed as parameter of the p
method call.
But as return
exits the method then the call to p
will never be processed.
So here a solution is to use and
instead of &&
.
method1 || method2 'hello'
This pretty common idiom can ends up to an error raising that can be confusing if we are not familiar with the precedence rules for ||
or
and method calls
.
Let’s have a look to the following example
The method1 or method2 ‘Jim’
idiom works as expected because method1
returns a string which is not falsy.
Note that here, the or
operator has a lower precedence than the method2 'Jim'
method call.
So, why the call to method1 || method2 'Jim'
raises a SyntaxError
?
Let’s slightly modify the above example to show you how Ruby executes the above code
As the or
operator has a lower precedence than the method2 ‘Jim’
method call then there is no syntax error in this idiom. method1
is processed and as it’s not falsy then method2 ‘Jim’
is not processed due to short-circuit evaluation in Ruby.
As the ||
operator has a higher precedence than the method2 ‘Jim’
method call then it tries to operate a OR
between method1
and method2
.
The problem is that the 'Jim'
string isn’t interpreted as a parameter of the method2
.
There is at least 3 solutions to overcome this issue:
- surrounding the parameter with parens:
method1 || method2('Jim')
- using the
or
operator instead - using
modifier-unless
keyword:method2 'Jim' unless method1
variable = a or b
Due to the fact that the assignment operator =
has a higher precedence than or
then this idiom can result to an unattended side effect
Here, the variable a
contains the value 42
when the variable b
is nil
.
Let’s slightly modify the above example to show you how Ruby executes the above code
For the variable a
, the ||
operator has a higher precedence than =
.
So nil || 42
is evaluated and the result is assigned to a
.
For the variable b
, the or
operator has a lower precedence than the =
operator. So nil
is assigned to b
first. Then 42
is evaluated.
So here, a solution is to use ||
instead of or
— depending on your needs.
block {..}
vs block do..end
Feel free to read Block as method argument in Ruby (2mn) if you’re not familiar with blocks in Ruby
Precedence also matters with Ruby blocks.
Indeed, blocks using brackets have higher precedence than blocks using do..end
.
Let’s illustrate this assertion with the following example
produces
method2 received block? true
method1 received block? false
method2 received block? false
method1 received block? true
Here, we can see that with the call to method2
using brackets syntax, the method2
receives the block and not the method1
.
In contrary, we can see that with the call to method2
using do..end
syntax, the method1
receives the block and not the method2
Let’s detail what happens in the above example by adding few parens
Here, we can clearly see that for the first call to method1
the block is attached to the inner method call — method2
.
For the second call to method1
, we can see that the block is attached to the outer method call — method1
.
So when we say that {..}
block has a higher precedence than do..end
block this has an influence on which method call the block will be attached to.
Voilà!
May I have your attention please 🎤🎤

Feel free to subscribe here: www.rubycademy.com
Thank you for taking the time to read this post :-)
Feel free to 👏 and share this article if it has been useful for you. 🚀
Here is a link to my last article: 2018: a year of blogging about Ruby