I was recently asked about the difference between using or
versus ||
in Ruby and thought it might make a good tip. They essentially do the same thing, but with one difference: operator precedence. You see ||
is evaluated before an assignment whereas or
is evaluated after an assignment. This is why you can create conditional assignments like so:
In the above code, if a user is found, then the variable is assigned that user. If a user is not found, then find_by_id
returns nil
(evaluates to false) and a new User is instantiated and assigned to the variable. If you were to use or
in the code above, then when find_by_id
returned nil the variable would be assigned nil as the assignment operator takes precedence over the or
operator.
Example
Here's a contrived example to show the difference between the two. Given the following class:
Here are some expressions and their results:
So far they look identical… But, let's change the order things are invoked.
Now we see the difference! When the invocation of Tester.b finishes, then the assignment operator is invoked, thus assigning false to the variable. Notice that Tester.a
is still invoked, but it is ORed with the result of the assignment.
Lazy (Shortcircuit) Evaluation
I was also asked if the conversational operators are always evaluated. The answer is: No. The are evaluated just as the non-conversational operators. From Programming Ruby, 2nd Edition:
Both and and && evaluate to true only if both operands are true. They evaluate the second operand only if the first is true (this is sometimes known as shortcircuit evaluation). The only difference in the two forms is precedence (and binds lower than &&).
Similarly, both or and || evaluate to true if either operand is true. They evaluate their second operand only if the first is false. As with and, the only difference between or and || is their precedence.
Precedence of and
and or
There is one other minor difference. The &&
operator takes precedence over the ||
operator so if you had an expression containing both, the &&
should evaluate first. With and
and or
they should be evaluated at an equal precedence, probably in the order they're encountered.
Conclusion
I use the conversational not/and/or
because I feel they make the code easier to read and force you to be explicit to account for the low operator precedence. I tend to use !/&&/||
sparingly (like using || for conditional assignment). Also, with compound expressions, I like to use parenthesis for clarity. Am I missing something? Do you know of a reason to prefer one or the other?
Update: Jay Fields has a post about this same topic. Marcel Molina, Jr. said in the comments that he prefers not to use either form as it is easy to introduce subtle errors.
Need web application development, maintenance for your existing app, or a third party code review?
Velocity Labs can help.
Hire us!