Veerasundaravel's Ruby on Rails Weblog

August 3, 2010

Using “and” and “or” in Ruby

Filed under: Ruby — Tags: , , , , , , , — Veerasundaravel @ 2:42 pm

If you use Ruby long enough, you will discover the and and or operators. These appear at first glance to be synonyms for && and ||. You will then be tempted to use these English oprators in place of && and ||, for the sake of improved readability.

Assuming you yield to that temptation, you will eventually find yourself rudely surprised that and and or don’t behave quite like their symbolic kin. Specifically, they have a much lower precedence. At this point, you may decide to swear off the use of and and or as too confusing.

But that would be doing your code a disservice. and and or are useful operators; you just need to understand their special place in Ruby programs.

and and or originate (like so much of Ruby) in Perl. In Perl, they were largely used to modify control flow, similar to the if and unless statement modifiers. A common Perl idiom is:

  do_something() or die "It didn't work!";

The and and or keywords serve the same purpose in Ruby. Properly understood, and and or are control flow operators, not boolean operators.

and

andIs useful for chaining related operations together until one of them returns nil or false. For instance:

  post = Post.find(id) and post.publish!

Here, the post will only be published if it is found, due to the short-circuiting nature of and. How does this differ from &&? Let’s take a look at a simple example:

  foo = 42 && foo / 2

What will we get when we evaluate this code? Let’s give it a try:

  NoMethodError: undefined method `/' for nil:NilClass
          from (irb):18
          from :0

Was that what you expected? As it turns out, with the relatively high operator precedence of &&, the way that code is actually parsed looks like this:

  foo = (42 && foo) / 2

…which is clearly not what we want. Contrast that to the and version:

  foo = 42 and foo / 2 => 21

…and now we have the answer we were expecting.

or

or, likewise, is useful for chaining expressions together. The best way to think about the chains constructed with or is as series of fallbacks: try this, if that fails try this, and so on. For instance:

  foo = cach[:foo] or foo = get_foo() or raise "Could not find foo!"

Conclusion

and and or, despite an apparent similarity to && and ||, have very different roles. and and or are control-flow modifiers like if and unless. When used in this capacity their low precedence is a virtue rather than an annoyance.

Thanks to: Avdi Grimm.

http://avdi.org/devblog/2010/08/02/using-and-and-or-in-ruby/

Advertisements

1 Comment »

  1. Thanks for bringing it here.

    Comment by Giang Nguyen — June 2, 2012 @ 5:14 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: