I understand the difference between || and or, or && and and, but what I don’t understand is this:
Consider a method that returns the value of @var, or initializes it if @var is nil for false.
As I came from JavaScript background, I would write it like this, since || has higher precedence than =:
def some_method
@var || (@var = MyClass.new)
end
or use or, since or has lower precedence:
def some_method
@var or @var = MyClass.new
end
or more concisely:
def some_method
@var ||= MyClass.new
end
But it so happened that this version also works:
def some_method
@var || @var = MyClass.new
end
I search the web but didn’t find useful results.
Most of them just tell the difference between || and or.
The operator precedence table clearly says that || has higher precedence than =.
I can even do a = b || c = d and Ruby sees it as a = (b || (c = d)).
Is this behavior documented somewhere or is it some kind of magic in Ruby?
P.S. CoffeeScript also has the same behavior.
Update / Clarification: This question is not about short-circuit evaluation. But about operator precedence. Please let me rephrase it again:
If || has higher precedence than =, then why does ruby sees a || a = b as a || (a = b), but not (a || a) = b and raise a syntax error?
Precedence becomes an issue only when there is ambiguity in the expression. In case of:
there is no ambiguity. The assignment operator
=makes sense only if there is a single variable on the left side of it (disregarding the complexities that arise from multiple assignment). It does not make sense to assign something to a variable called “@var || @var“. Therefore, there is no ambiguity. The only way to interpret the above expression is to interpret it as:Therefore, precedence is not an issue here.