The order of math operations is very important in programming language. If you don’t know them well, you can get completely different results, than you expect. And your code can be just wrong. You need to know the rules. Is the order similar like in math? Or maybe the algebraic expression is interpreted from the left to the right? Do you know how does this look like in Ruby? Let’s check it.

``````2 + 2 * 2
=> 6
``````

This is not 8. It is 6. You can see here that multiplication is stronger then addition. In this case we will say that multiplication has higher operator precedence then addition. This is exactly the same like we have learned at school on Math classes. To show you this more precisely, we have:

``````2 + (2 * 2)
=> 6

(2 + 2) * 2
=> 8
``````

OK, but how will I know that? There are many different operators. Well, you need to remember the table of operators order, from Ruby documentation - operators precedence:

``````!, ~, unary +
**
unary -
*, /, %
+, -
<<, >>
&
|, ^
>, >=, <, <=
<=>, ==, ===, !=, =~, !~
&&
||
.., ...
?, :
modifier-rescue
=, +=, -=, etc.
defined?
not
or, and
modifier-if, modifier-unless, modifier-while, modifier-until
{ } blocks
``````

As you can see here `*` is higher than `+`, so it has higher precedence.

## Examples

### Boolean operators

``````1 || 2 && nil
=> 1

1 or 2 and nil
=> nil
``````

On the first look, logic is the same, but we get different results. But when you take a look closely, you will see the difference. Order of calculations. In the first example, the order looks like `(1 || (2 && nil))`. We get `nil` from `2 && nil`. And then we have `1 || nil` so this is `1`. Well, I lied a little bit here. Our interpreter is smarter, than you can think of. Because we have this `||` operator. It has been truthy always when left hand side is truthy, so it checks only the first part of our expression. Check here:

``````a = 0
=> 0

a = 1 || a = 2
=> 1

a
=> 1
``````

In the beginning, we assigned `0` to `a`. Then we check condition together with assignments. If we check also right hand side, we should get `2` assigned to `a` variable. But we get `1`. We get `2` only, when the left hand side is falsy. For example:

``````a = false || a = 2
=> 2

a
=> 2
``````

In the second example `1 or 2 and nil` order of operations is completely opposite: `((1 or 2) and nil)`. First, we check `1 or 2`. We get `1` and then we check `1 and nil`, so the final result is `nil`.

To understand better the differences between these two notations, let’s check all possibilities here in table:

abca || b && ca or b and c
`false``false``false``false``false`
`false``false``true``false``false`
`false``true``false``false``false`
`true``false``false``true``false`
`true``true``false``true``false`
`true``false``true``true``true`
`false``true``true``true``true`
`true``true``true``true``true`

There are 2 cases, where you see the difference between operators `||` and `&&` and operators `or` and `and`.

### Assigments

This example is related with boolean operators, but also with assignment:

``````foo = 1 && 2
=> 2
foo
=> 2

foo = 1 and 2
=> 2
foo
=> 1
``````

Both of this logic expressions give us `2` as truthy result. But there is one difference here. In first case `foo` equals to `2` and in second example `foo` is `1`. This is related, of course, with operator precedence. Because `&&` has higher precedence than `=` in the first example we have:

``````foo = (1 && 2)
``````

In second example, order of those operations is different. `=` has higher precedence, then `and` so we have:

``````(foo = 1) and 2
``````

Similar behavior we will see for `||` and `or` operators. This will be visible only, when the first part of the expression will be `false` or falsy value. For truthy value, we will see no difference. Both expressions will behave the same:

``````# first part of condition is falsy
foo = false || 2
=> 2
foo
=> 2

foo = false or 2
=> 2
foo
=> false

# first part of condition is truthy
foo = 1 || 2
=> 1
foo
=> 1

foo = 1 or 2
=> 1
foo
=> 1
``````

I would like to explain, why we don’t see any difference. For `foo = 1 || 2` we should set brackets like this `foo = (1 || 2)`. From logical condition `||`, we get `1` and we assign it to `foo`. In a second example `foo = 1 or 2`, first, we do the assignment and then we check the condition. The result is the same, but order of those operations is different. This is worth to be remembered!

In the end of this section, I would like to show you one more example. I think, it is a very interesting one. It is more complex because it uses `=`, `&&`, `and` and `<<`.

``````s = '2'

s = '1' && s << '3'
=> "23"

s = '2'

s = '1' and s << '3'
=> "13"
``````

Let’s go step by step to understand, what is going on in here. In the first example we have `&&`. We know that, it has quite high precedence, but predecence for `<<` is higher, than `&&`. So the order of calculations here looks like: `s = ('1' && (s << '3'))`. First, we concat `'3'` to string. We get `s = ('1' && '23')`. Now we do `&&`, so the result is `'23'`.

In the second example we have order like `(s = '1') and (s << '3')`. We start from assignments. So `s` is now `'1'` not `'2'`. Then we calculate right hand side part and we get `'1' and '13'`, so the final result is `'13'`.

### Methods & boolean operators

We still are in an area of boolean operators. This example will show you, how they behave with method calls without specifying brackets. As you know, in Ruby, you can omit brackets in some cases. But when you work with boolean at the same time, you need to be careful.

We declare our method and first example of usage:

``````# declare method
def method(char)
puts "My char id #{char}"
end

# example 1
method 'a' || 'b'
My char id a
=> nil
``````

In this example, first operator `||` will be called. We will get `'a'` from it. This is why we see `"My char id a"` text. But because the method is displaying only the test and it doesn’t return anything, we see `nil` value in the end. This is important, that our method always return `nil`. You will see why in the next examples. Order of operations was: `method('a' || 'b')`.

Let’s go to the next example:

``````# example 2
method 'a' && 'b'
My char id b
=> nil
``````

In the second example, the order is the same `method('a' && 'b')`. First, we do `&&` operation and we get `'b'` from it. Then we call our method. So this is why `'b'` is in our text.

``````# example 3
method 'a' or 'b'
My char id a
=> "b"
``````

In the example 3 you can notice a different behavior. As we already know, the order will be `method('a') or 'b'`. This is why we see `'a'` in text, but then we need to finish this logical expression. Because our method return `nil` and this is falsy value, we have `nil or 'b'`. In the end, we see `'b'` is returned, not from the method, but from all expression.

``````# example 4
method 'a' and 'b'
My char id a
=> nil
``````

For example number 4, the order of operation is the same like for example 3. We have `method('a') and 'b'`. Text is `"My char id a"` because of a `'a'` argument in the method. Then function return `nil`, so we have `nil and 'b'`. This is why we see one more time `nil` in the end.

OK, and now we will still stay in method calls context, but with different example. We declare two methods, one with no arguments and one with an argument.

``````def method1
puts 'Call Method 1'
end

def method2(text)
puts "Call Method 2 with #{text}"
end
``````

Now we check, what will happen to `or` and `||` conditions.

``````method1 or method2 'foo'
Call Method 1
Call Method 2 with foo
=> nil
``````

First example looks OK. We call `method1`, which display `"Call Method 1"` text and return `nil` (as we know from example above). Then, we call `method2` with one argument `'foo'`. We display text and return `nil`. Order of operations: `method1() or method2('foo')`. Everything is fine. Let’s look at the second example.

``````method1 || method2 'foo'
Traceback (most recent call last):
1: from /home/agnieszka/.rvm/rubies/ruby-2.5.3/bin/irb:11:in `<main>'
SyntaxError ((irb):32: syntax error, unexpected tSTRING_BEG, expecting keyword_do or '{' or '(')
method1 || method2 'foo'
^
``````

Something went wrong. We got an error. This is because of precedence. Order of operations in this case is: `(method1 || method2) 'foo'`. We can show it in a more descriptive way `(method1() || method2()) 'foo'`. Our interpreter doesn’t know what to do because of two reasons. One, `method2` should have one argument and it didn’t get any. And the second one, more important, which we see in the error message. Interpreter see some free text `'foo'` without any operator in the same line with calling methods. To fix that, we need to say explicitly, what we want: `method1 || method2('foo')`

The same problem you will get when instead of `method2` you will use `raise` or `return` or any other method. If you like, just play a little bit with them.

### Blocks

Time for blocks. We need to be aware that blocks with `{}` have higher precedence than blocks `do ... end`. This is not exactly specified in our order table, but in the documentation, you can find a small note about it. So, let’s check this out. We will prepare two methods with blocks. In one we will call the block with `{}` and in the second with `do ... end`.

``````def foo(options = {}, &block)
puts "Foo has block: #{block_given?}"
end

def bar(options = {}, &block)
puts "Bar has block: #{block_given?}"
end

foo a: bar { 1 }
Bar has block: true
Foo has block: false
=> nil

foo a: bar do 1 end
Bar has block: false
Foo has block: true
=> nil
``````

In the example one, the order is like here: `foo(a: (bar { 1 }))`. First, we will call `bar` method with a block. It will return `nil` and then we will call method `foo` with only hash parameter. It will look like this: `foo(a: nil)`. So, this is why we don’t get a block in method `foo`.

In second example the order is different: `foo(a: bar) do 1 end`. It will be even better, to split it into separate lines.

``````foo(a: bar) do
1
end
``````

At first, we call method `bar`, but without any arguments and without a block. This is why we see this in the text: `"Bar has block: false"`. Then we call method `foo` with hash `{ a: nil }` as `options` and with block. We could even omit this hash parameter in the call of these two methods. It would be working the same. At least for displaying text on a screen. You can try to do that your own `foo bar { 1 }` and `foo bar do 1 end`.

### Other examples

``````array = []
a = 1
b = 2
array << a + b
=> 
``````

This example behaves like we expect. First, we sum `a` and `b` and then we put value in the array. If you check in our precedence table `+` has higher precedence than `<<`.

In next example also everything will be all right. `+=` and `*=` has lower precedence than `+` and `*`. So you can omit brackets:

``````a = 1
b = 2
sum = 0
multi = 1

sum += a + b
=> 3
sum
=> 3

multi *= a * b
=> 2
multi
=> 2
``````

Now precedence related to ranges. Because `+` and `-` has higher precedence than range, you can omit brackets here and everything will be fine:

``````n = 9
=> 9

1..n - 1
=> 1..8

(1..n - 1).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8]
``````

This is like doing `1..(n - 1)`.

## Summary

• Be aware of operators precedence in Ruby.
• If you are not sure about precedence, put the right brackets or even better: check in the documentation.Also do the tests ;]
• Sometimes, even if I know precedences in Ruby, I like to leave brackets. It is more readable for me. Like here: `method('a' && 'b')`. I know that this notation `method 'a' && 'b'` is correct and do exactly, what I want, but I like to be more specific here. This is more “Tell, don’t ask” approach.

That’s it. If you have any other precedence examples, which were not mentioned here, feel free to share them in the comments. Thank you for reading and see you next time!