Stumped:beginners question

I’m having a hard time with both getting my branching correct as well
as my loop.
In this little program, the survey taker asks expecting a “yes” or
“no” (currently not working correctly). If any other response is
given, then the survey taken says…please answer with yes or no…

I commented out the return at the end since I’m not even sure what
that’s doing.

TIA
Stuart

$stdout.sync = true

def ask question
reply = nil
while (not reply)
puts question
reply = gets.chomp.downcase

  if (reply !='yes' || reply != 'no' )
      puts ' Please answer "yes" or "no".'


  elsif reply == 'yes'
      reply = true
  else reply == 'no'
      reply = false
  end
end

end

#reply # This is what we return (true or false).
#end

  if (reply !='yes' || reply != 'no' )
      puts ' Please answer "yes" or "no".'

This is a problem. No matter what answer you provide, at least one of
the two inequality conditions will be true, which means the ||
expression will always be true.

Try this instead:

if (reply != ‘yes’ && reply != 'no)
puts ‘Please answer “yes” or “no”.’

On Jun 25, 2006, at 9:32 AM, Dark A. wrote:

 if (reply !='yes' || reply != 'no' )
     puts ' Please answer "yes" or "no".'


 elsif reply == 'yes'
     reply = true
 else reply == 'no'
     reply = false
 end

Try:
if (reply != ‘yes’ && reply != ‘no’)

OR:

case reply
when 'yes': reply = true
when 'no' : reply = false
else puts 'please answer "yes" or "no"'
end

In your original, reply is going to be != to at least one of the two
alternatives!

-Rob

Rob B. http://agileconsultingllc.com
[email protected]
+1 513-295-4739

On Jun 25, 2006, at 14:45, Rob B. wrote:

end
end

In your original, reply is going to be != to at least one of the
two alternatives!

There’s trouble with your loop condition as well: you’d want to
terminate the loop when reply == false, but when reply == false, the
loop won’t terminate, since !reply == true. Similarly, when you get
a bad answer, reply == “foo” (or something), so !reply == false, and
the loop will terminate.

In this case, I’d use a case statement like R.B. suggested, but with
an explicit return to break the loop:

while true
puts question
case gets.chomp.downcase
when ‘yes’ : return true
when ‘no’ : return false
else puts ‘please answer “yes” or “no”’
end
end

Or, if you don’t like explicit returns, maybe something like this:
while (not reply)
puts question
reply = gets.chomp.downcase
if (reply != ‘yes’ && reply != ‘no’)
puts ‘please answer “yes” or “no”’
redo # restarts the loop without checking the condition
end
end

convert yes/no to true/false here so that it doesn’t

interfere with the loop.

reply == ‘yes’ ? true : false

matthew smillie.

I tried this option first:
if (reply != ‘yes’ && reply != ‘no’)

Which now if response is anything but those two answers brings up the
“please answer yes or no…”

However, I’ve added the return reply , and if response is anything but
yes or no, it notifies responder but still moves on to the next
question. The case statement is preferable but it hasn’t been
introduced yet to my learning material.

def ask question
reply = nil
while (not reply)
puts question
reply = gets.chomp.downcase

  if (reply !='yes' && reply != 'no' )
      puts ' Please answer "yes" or "no".'


  elsif reply == 'yes'
      reply = true
  else reply == 'no'
      reply = false
      return reply
    end

end

end

If I’m assimilating this correctly then if something is not equating
to false then it automatically equates to true. Which makes sense.
However, sadly I must say setting up the loop is still a problem for
me to grasp. (Maybe I should consider another hobby :))

Here it’s new incarnation I’m still failing to catch the error and
repeat the question.

def ask question
reply = false
while not reply
puts question
reply = gets.chomp.downcase

case reply
when ‘yes’: reply = true
when ‘no’ : reply = false
else puts ‘please answer “yes” or “no”’
end
end
end

Note - When I attempted to use this:

mexicanfood.rb:10: parse error, unexpected ‘:’, expecting kEND
when ‘no’ :return = false

I’m seriously wondering if this obstacle to my understaning is an
indicator of my innate skills or if spending more time will help to
enlighten and break through.

Stuart

while true
puts question
case gets.chomp.downcase
when ‘yes’ : return true
when ‘no’ : return false
else puts ‘please answer “yes” or “no”’
end
end

ruby was spitting out an error:

I’m just going to rewrite this, because there are a bunch of bad
things in it.

def ask(question)
response_is_valid = false
result = false
while !response_is_valid
puts question
reply = gets.chomp.downcase
case reply
when ‘yes’
result = true
response_is_valid = true
when ‘no’
result = false
response_is_valid = false
else
puts ‘Please answer “yes” or “no”.’
end
end
result
end

Part of the reason you’re getting confused is that you’re using the
‘reply’ variable for several things: to store the entered string, to
store the final result, and to determine whether a valid response has
been entered. That’s called overloading a variable, and is bad
programming practice. In the version above (which is probably a bit
more verbose than it really needs to be, but should be easier for you
to work with), I’ve split those things out into three separate
variables.

Cheers,

Pete Y.
http://9cays.com/

On Mon, Jun 26, 2006 at 08:57:05AM +0900, Pete Y. wrote:

  when 'yes'

end

much simpler than using the case statement:

def ask(question)
puts question
reply = gets.strip.downcase
while ("#{reply}" != “yes”) && ("#{reply}" != “no”)
puts ‘please answer “yes” or “no”’
puts question
reply = gets.strip.downcase
end
end

On Jun 25, 2006, at 16:16, Dark A. wrote:

If I’m assimilating this correctly then if something is not equating
to false then it automatically equates to true. Which makes sense.
However, sadly I must say setting up the loop is still a problem for
me to grasp. (Maybe I should consider another hobby :))

Basically, only ‘nil’ and ‘false’ are false in boolean expressions,
everything else is true. ‘nil’ doesn’t equate to ‘false’, however:
nil == false # => false

I tried the code and don’t get an error on it - maybe it’s a version
problem? In any case, the standard syntax of a case statement should
work for all versions, it generally looks like this:

case var
when ‘something’
puts “hello world”
when ‘another thing’

else

code for all other cases

end

Read up on it - Ruby’s case statement is enormously flexible.

As for the loop, what you need to ask yourself is “what are the
conditions where the loop should terminate?” and remember that those
conditions are evaluated only at the start of the loop (for while-
loops).

So, for your case:
loop condition: not reply
| stops? | should stop?
possible values of | true | yes | yes
reply at the start | false | no | yes
of the loop | (str) | yes | no

Where (str) is the user’s input. It’s pretty obvious that checking
the truth-value of reply isn’t going to work as a loop condition in
this case.

Basically, you need to think up another condition for your loop, one
that is only true when you want the loop to perform another
iteration, and is only false when you want the loop to stop. The
simplest way would be to create a variable specifically to track the
loop’s state:

continue = true
while (continue)
reply = gets.chomp.downcase
case reply
when ‘yes’
continue = false
reply = true
when ‘no’
continue = false
reply = false
else
puts ‘only “yes” or “no”’
end
end

I’ll point out that this isn’t a very elegant solution, though it has
one major advantage: it makes the behaviour of the loop absolutely
explicit and understandable. It’s extremely difficult to come up
with the compact and elegant solutions without understanding the
basic ones like this.

best of luck,

matthew smillie.

Well, now the author has introduced us to the wonderful world of
recursion. Removes the need for the loop. I imagine very useful in
various situations.

Stuart

Hi –

On Mon, 26 Jun 2006, Cliff C. wrote:

case reply

result
end

much simpler than using the case statement:

def ask(question)
puts question
reply = gets.strip.downcase
while (“#{reply}” != “yes”) && (“#{reply}” != “no”)

You’re working too hard :slight_smile: No need to do string interpolation:

while (reply != “yes”) && (reply != “no”)

or even:

until %w{ yes no }.include?(reply)

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

See what the readers are saying about “Ruby for Rails”!