back

and vs && (double ampersand) in Ruby

Many people seem to prefer using and instead of && in Ruby, as it sounds more like speech.

However, do note that it’s slightly different from using &&. The difference is important enough that I think you should avoid using and.

&& (double ampersand) vs and
The difference is that && has higher precedence. This means that it will get evaluated before and.

So, we end up with weird stuff in some situations. This is perhaps most likely to cause weirdness when using the ternary operator, as it is evaluated before and. Here’s a real life example:

So, clearly in the third case the alien would have killed you, because it doesn’t speak English so it didn’t know what you meant by false.

What’s going on is that the order that the code is being evaluated in is changing the result.

So, here is what happens in case 3 (note that the same thing is happening in case one, but we would not have noticed it).

1) ternary: alien ? ‘hello’ : ‘silence’ #=> “hello”
2) and: speaks_english and ‘hello’ #=> false and hello
3) => false

Whereas, in cases two and four, we have

1) &&: speaks_english && alien #=> false
2) false ? ‘hello’ : ‘silence’ #=> silence

Also note that and comes after the assignment operators as well, so you will also have trouble with something like this:

In this example, we would end up giving a true sword despite our intentions of giving a false one. This example highlights how even though the final return value of the entire expression could be what you want, a variable could be getting assigned some value that you weren’t expecting.

So, in the second example above, since the = operator comes before and, the sword is first getting assigned the value of hammer_of_truth (true), before the expression on the right is evaluated.

Then, since true && anvil_of_false returns false, we still get the right return value, but when we look at sword it’s true.

In my opinion, this seems like a good reason to never use and unless you really mean it. Even in those cases, however, it’s likely that other coders will not see the subtlety, and misunderstand what you are meaning to do. I have a bad habit of indiscriminately replacing and with && (I’m used to C), so if I saw a method like the one above, I might unknowingly destroy someone’s logic.

So, it seems like the best thing to do is always use &&, and if you mean to do something that would call for and, just use parenthesis, e.g. if you actually wanted sword to be true: (sword = hammer_of_truth) && anvil_of_false.

This is slightly uglier as it involves the extra parens, but imo is much clearer than assuming everyone who reads your code in the future will quickly be able to tell that you really meant to use and.

December 08, 2008

  1. Philip (flip) Kromer says:

    The +or+ operator, used with care, can be useful to short-circuit a /statement/ rather than an /expression/. Ex:

    1
    2
    3
    4
    
    def fetch_all_friends user
      friend_ids = api.get :friend_ids, user or return []
      ... fetch user records for each friend ...
    end
    

    I can't think of a good case for +and+ ... it's usually best done as "do_action if condition" or "do_action_1 && do_action_2".

  2. Mischa says:

    @mrflip

    Interesting idiom. Definitely something I might start using a lot. Thanks!