"unless" statement inside of "if" statement not working


#1

print "are you hungry?"
answer = gets.chomp
answer.downcase!
if answer === "yes" 
    hungry = true 
elsif 
unless answer === ("no" || "yes")
puts "yes or no"
else
    hungry = false 
end
end

if answer === ("no" || "yes")
    unless hungry === true
  puts "I'm writing Ruby programs!"
else 
  puts "Time to eat!"
    end
 
else puts "use your head"
end

with this, responding with "no" answers "i'm writing Ruby programs!"
responding with anything other than yes or no brings " yes or no" "use your head"
and responding "yes" is supposed to bring "Time to eat"

however, when i put "yes" it just brings back "use your head"

i can't figure out what mistake i am making. can anybody help me?


#2

Im not sure, this is just a guess, but why there are 2 ends on lines 10 and 11?


#3

one for the "if" statement, and one for the "unless" statement within that if statement.

print "are you hungry?"
answer = gets.chomp
answer.downcase!
if answer === "yes"
hungry = true
elsif
unless answer === ("no" || "yes")
puts "yes or no"
else
hungry = false
end
end

as far as i can tell, this part of the code works perfectly,.
if i check at the end, answering "yes" makes hungry == true, and "no" makes hungry == false, while giving neither of those answers brings the "yes or no" message.

the issue is with the lower part of the code.

if answer === ("no" || "yes")
unless hungry === true
puts "I'm writing Ruby programs!"
else
puts "Time to eat!"
end

else puts "use your head"
end

so, if the answer was either "no" or "yes" the if statement should run, which should start the "unless" statement just like in the previous code. so if hungry does not == true, it should put "i'm writing ruby programs!" which it successfully does.
if hungry != true, the unless statement SHOULD run the else statement which puts "time to eat!" and then there is an "end" to close the unless statement.
then, back to the original "if" statement, if answer is neither "no" or yes", it should put "use your head", which it will successfully do.

some reason though, instead of running the else statement within the unless statement, having hungry == true skips that line entirely, and goes to the last else which is outside of the "unless" statement, and shouldn't be running unless answer === ("no" || "yes")

so i have no idea why it skips, and the unless statement doesn't seem to be contained.

removing any of the "end"s will cause the code to fail, which should mean they close the "unless" statements as i expect them to.


#4

Won't this always be true?

answer = 'yes'
if answer === 'no' || 'yup'
    print answer
end

# yes

just as,

print "no" || "yes"

# no ... always.

It's the first non-empty string in the expression, so short-circuits.

Try,

if answer === 'no' || answer === 'yes'

#5

This is stretching it a bit but the result is the same. It's just an experiment:

unless ['no','yes'].include?(answer)

#6

works perfectly, although i'm not sure i understand the logical error i made, or the way you described it.

thank you very much, although if you could try rephrasing how mine did not work i would appreciate it.

if answer === 'no' || answer === 'yes'

if answer === 'yes'
i see how it checks "is answer 'no'? (false), OR is answer 'yes' (true)" then it runs the "if" code as true.

but

if answer === ('no' || 'yes')

i see it as checking "is answer ('no'? (false) OR 'yes' (true)) so it runs the if code as true, while if answer = 'neither' then it should return false while checking both 'no' and 'yes', which should make it run the 'if' statement as 'false'?

how is

answer = 'yes'
if answer === 'no' || 'yup'
    print answer
end

true when answer is neither 'no' or 'yup'?

thank you again for the help.


#7

In Ruby, everything but nil and false is truthy. 'no' is truthy. Only one operand in an OR expression needs to be truthy, so the first one to occur causes Ruby to give up on the rest and follow the true branch of the if statement.


#8

but why is it truthy when answer != 'no' ?
sorry for the trouble, i'm just having difficulty wrapping my head around this for some reason.


#9

These two expressions are quite different from each other:

if answer === 'no' || 'yup'

and

if answer === ('no' || 'yup')

My very first question concerning this last one can be answered, no. It will always be false, unless answer is identical to the first operand. When answer is "yes" and the first operand is "no", the result is false. Since the first operand is truthy (is not nil or false) it won't matter what the second one is. It will never see the light of day.

Take away the brackets like the earlier example and we have a completely different expression. This time the operands are, answer === "no", and "yup". This will always be truthy because the second operand is truthy. In the event the first yields nil or false, the second becomes the fallback return object.

    answer = 'yes'
    puts answer === 'no' || 'yup'
    # yup
    puts answer === 'yes' || 'yup'
    # true
    puts answer === ('yes' || 'yup')
    # yes