Sunday, November 16, 2008

|| and && operators may not be doing what you expect

When you use || and &&, you may think that you are playing with true/false values. For instance, a condition that uses || or && will give you back true or false.

I found out recently that this is sometimes true (and sometimes not)! Now, what am I talking about? I always thought that if you evaluate (true || true), the expression evaluates to true because at least one of them is true. Well, apparently, it does evaluate to true, but not for the reason I had thought.

In Ruby, when you evaluate (true || true), what it is actually doing is evaluating the first condition. If it is truthy (ie. not false or nil) you get the first condition back. If it is falsy (ie. false or nil), you get the second condition back. So the following occurs:

('blah' || true) #=> 'blah' - not true!
(false || 'blah') #=> 'blah' again!

For &&, if the first condition is falsy, you get the first condition back. If it is truthy, you get the second condition back. Check it out:

(true && 'blah') #=> 'blah'
(nil && true) #=> nil - not false!

Using || and && still work in 'if' statements as expected, but it doesn't work the way as first thought. With this new insight, you can use || and && for shortcuts.

Instead of:

if options[:product].nil?
product = Product.new
else
product = options[:product]
end

You could do:

product = options[:product] || Product.new

And instead of:

unless product.nil?
name = product.name
end

You coud do:

name = product && product.name

Obviously, use these shorthands with caution, as it can convolute readability for other readers. On another note, JavaScript also follows this evaluation. Have fun!


W

No comments: