I was recently asked about the difference between using
|| 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
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
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.
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
or they should be evaluated at an equal precedence, probably in the order they're encountered.
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?
Need web application development, maintenance for your existing app, or a third party code review?
Velocity Labs can help.Hire us!