When I first started learning Ruby, I was excited to discover that Ruby has the keywords
or as boolean operators. I quickly got into the habit of writing all of my boolean statements with these, instead of the more conventional
||, because my code became so much more readable. I thought the word versions of the boolean operators were part of Ruby’s mission to make code more like spoken language. For example, the following is valid Ruby syntax, and you don’t have to know the language to know what it does.
However, the story about Ruby’s boolean operators is not quite that simple. If you’re like me and you get excited over the idea of clean, readable code, you might run off and mass-replace all of your
and’s, and your
or’s. Before you do that, open up your favorite Ruby console (I’m partial to pry, myself) and try the following:
Now let’s try doing it the cool way:
Is Ruby really trying to tell me that
true and false evaluates to
true? Nope. It turns out Ruby just has different precedence rules for and and &&. Now, this example may prompt you to avoid the word versions of the boolean operators altogether, and you wouldn’t be alone — the first Google result when searching “Ruby Style Guide” suggests you should never use them. But I say fear not, as
or do have their ideal uses. They are much easier to understand if you stop thinking about them as boolean operators and start thinking of them as control flow operators! Allow me to explain.
The first edition of the Pragmatic Programmer’s book on Ruby has an excellent table listing the order of operations. It’s old and talks about Ruby 1.6, but we’re at Ruby 1.9.3 right now and the rules haven’t changed, and they likely won’t change for a long time. As you can see, and is really just a low-precedence version of &&. Its main purpose is to control the flow of logic, since its low precedence and short-circuiting behavior help ensure that all of its left-hand side gets evaluated before any of the right-hand side does. This is useful when you want to chain operations together and have them execute until one of them returns a false-y value (false or nil).
Let’s revisit the above example with this behavior in mind. Using parentheses to illustrate the order of operations, the following illustrates how
and operate differently.
Think of the second example like this: “If
a = true evaluates to a truth-y value (anything but false or nil), run
false. Otherwise, return the result of
a = true.” It could have just as easily been written like this.
The most common use for the
and operator is for operations that depend on the success of other operations. Something like this.
or works in just the same way, short-circuiting execution of its right-hand side if its left-hand side evaluates to a truth-y value (anything but false or nil). It is most commonly used to throw errors if something goes wrong.
The above example could have just as easily been written like this, depending on your style.
I prefer the or version in this case as the code gets run from left to right, the same way it is read.
Watch out, though, as the
or keywords still have slightly higher precedence than their more mainstream control-flow cohorts (
…gets evaluated in this order:
A final important point is that
or have the same precedence, unlike their symbolic counterparts where
&& evaluates before
||. This means that operations chained together with with
or always get evaluated from left to right.
…gets evaluated in this order:
And here’s what they would look like with the symbolic boolean operators.
…which gets evaluated in this order:
The main thing I would take away from this is to never be afraid of using
or. They may not be suitable for regular boolean logic, but they have their place when they are used to control the flow of your code, often making it even more readable.
Happy coding! Let us know your thoughts in the comments. 🙂