LuminaChen
LuminaChen

Reputation: 135

Ruby If and Unless conditional explanation

I want to ask for a little explanation about if and unless, I know the two of this is an opposite of each other. All of this time I have used both without no problem until now I find something weird. Let's check my code :

ausysdir = AUDIO_SYSTEM_FOLDER_NAME 

Dir.mkdir(ausysdir) if ausysdir != "" && !File.directory?(ausysdir)     # Number 1 
Dir.mkdir(ausysdir) unless ausysdir == "" && File.directory?(ausysdir)  # Number 2

Now in the directory I work the folder ausdyr is already exist. But from the code above the the number one conditional which is if not return an error(this is what I expected, so great), But not with number 2 conditional which is unless, when I think that if and unless is an opposite, then my syntax above should be correct, am I right? Or my syntax is wrong? Or Unless have a different behaviour? Or do I missed something here?

Thank you very much.

EDIT : When I mean error, is an exception because the file is already exist.

Upvotes: 0

Views: 593

Answers (2)

Jay Mitchell
Jay Mitchell

Reputation: 1240

TL;DR Don't use unless with more than one condition. Most people have to think too hard to understand it, and then have about a 50/50 chance of getting it right.


Here is a test of two booleans using if/unless and &&/or:

def test(first, second)
  puts "#{first}, #{second}"
  puts "  ...passes if #{first} && #{second}" if first && second
  puts "  ...passes unless #{first} && #{second}" unless first && second
  puts "  ...passes if #{first} || #{second}" if first || second
  puts "  ...passes unless #{first} || #{second}" unless first || second
end

test(true, true)
test(true, false)
test(false, true)
test(false, false)

The results:

true && true
  ...passes if true && true
  ...passes if true || true
true && false
  ...passes unless true && false
  ...passes if true || false
false && true
  ...passes unless false && true
  ...passes if false || true
false && false
  ...passes unless false && false
  ...passes unless false || false

Your first condition boils down to if false && false, according to the false, false results above, if false && false doesn't pass. Reaction: Pretty straightforward and easy to see.

Your second condition boils down to unless false && true, according to the false, true results above, unless false && true does pass. Reaction: That seems like it possibly might make sense if I think about it some more.

Upvotes: 1

mu is too short
mu is too short

Reputation: 434585

unless expr is the same as if !expr. But !(a && b) is not !a && !b as you seem to think, it is actually !a || !b (this is one of De Morgan's laws BTW). So your if and unless statements are not at all equivalent.

Build the truth table if you don't believe me. Then study some Propositional Calculus (which every programmer should be familiar with) if you don't believe your truth table.

If your if works then you're unless would be:

unless ausysdir == "" || File.directory?(ausysdir)

Upvotes: 1

Related Questions