Don’t use or/and in ruby – ever.
Posted: June 11th, 2010 | Author: michael | Filed under: Engineering, Ruby | Tags: and, bad, boolean logic, or, Ruby | Comments OffIn ruby, I see a lot of things like the following
1 2 | some_func_call if x or y some_other_func_call if x and y |
While this technically will work in this case, it’s fairly bad practice. Multiple conditions after an action is another annoying thing to read from a developer standpoint, but that’s an entirely different post. I’m sure you’re asking now – what does that statement above have to do with not using and/or instead of &&/||. I mean, and/or makes more beautiful code and you’re supposed to write beautiful sonnets and haikus in ruby, aren’t you?
Let’s show an example before we get into an explanation.
1 2 3 4 | true || true && false => true true or true and false => false |
For those of us that took a discrete math class in college, we know the distributive property applies to boolean logic in the following way (Image is from wikpedia from the article linked if you’re more curious about boolean logic).
Okay, so we have two statements that look nearly the same outside of operators (english vs. c style operators). Let’s apply the distributive property to both of them
1 2 3 4 5 6 7 | #We'll use the variables so it's even more obvious and corresponds. a = b = true c = false #a or b and c = (a or b) and (a or c) (a or b) and (a or c) => true |
Now, one may argue – why aren’t I using parens in the a or b and c. The reason is – and this is the huge thing I don’t quite understand about ruby’s and/or – is that logical and has a higher precedence than logical or (complement, or ! in ruby has the highest precedence).
Therefore, I should be able to use a or b and c and assume the b and c portion will be computed first – but this isn’t the case. The and/or operators in ruby break distributivity. Why? I have no idea – but it’s generally a bad idea to use the english versions (especially in public code!). The likely issue that will occur is someone who knows how to program but doesn’t realize ruby’s weird precedence issue (I’d guess a lot of people don’t realize it) will go in and assume they can further compose the conditional in ways that would break all logic for that stub of code. Debugging those sorts of issues are extremely hard as well since they are technically (from ruby’s perspective) correct while being logically flawed.