jd77 jd77 - 1 month ago 5x
Ruby Question

Logical OR order of operations/precedence not as expected


The binary "or" operator will return the logical disjunction of its
two operands. It is the same as "||" but with a lower precedence

As I understand it, as || has a higher precedence than "or", the code below will first test if 'b' is true, then 'c', and then if both are false will test 'a'. I would like to witness this but am not sure if my understanding is incorrect, or simply my test.

a = true
b = false
c = false
p a or b || c
==> true #but were b and c checked as expected?

My attempt to test this is as follows..

def atest
a = "string a"
a.include? 'string'

def btest
b = "string b"
b.include? 'string'

def ctest
c = "string c"
c.include? 'string'

puts "#{atest or btest || ctest}"
==> string a

I expected 'string b' to be returned... I'm completely new to programming since a week ago so I'm not sure, is my code wrong or is my understanding of the quote wrong?


In Ruby, &&, and, ||, and or are short-circuit operators:

[...] the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function evaluates to true, the overall value must be true.

In your example:

a or b || c

Ruby evaluates a, sees a truthy value and immediately returns it, without evaluating b || c.

or's lower precedence means that the expression is evaluated as:

a or (b || c)

instead of:

(a or b) || c

Just like

1 + 2 * 3

is evaluated as:

1 + (2 * 3)

because + has lower precedence than *.

But it doesn't change the order of evaluation. 1 is still evaluated before 2 * 3.

Also note that due to or's very low precedence

p a or b || c

is evaluated as:

(p a) or (b || c)

Neither b nor c will ever be printed this way.

Further readings: