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

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 Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
+1 513-295-4739

···

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

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

     elsif reply == 'yes'
         reply = true
     else reply == 'no'
         reply = 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".'

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 Yandell

···

On 25/06/2006, at 11:32 PM, Dark Ambient wrote:

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

Alright, if there are any people remaining that have some patience to
repeat I'm running into the same problem again. And for now I really
want to stick to while,because now it's a real sticking point for me.
If I do nothing else in Ruby, mastering the while statement is a
must.:slight_smile:

So here I've created a method. See inline for why I think it should work.

#sort is the parameter for the alpha method
def alpha sort

#setting up my arrays
  s_words =
  u_words =

#assign a blank string to sort to start things off
  sort = ' '

# what I'm trying to say here is that if sort remains empty continue the loop
while sort == ' '
# to prompt the user to enter something I've added the puts statement
  puts 'Please enter a word to be sorted'
#Now I'll assign sort to whatever the user inputs.
  sort = gets.chomp.downcase
#Now I want to put the string into the array.
  u_words.push['sort']
#I haven't thought it completely through but I'll probably want to
give the user a
#surrender word to stop the loop. Still I think at this point it
should loop at least
#once. Sadly, it does not, so either I'm thick or this is a hard
concept for me. #Polymorphism seems easier to grasp right now
  end
end

TIA
Stuart

···

On 6/26/06, Robert Dober <robert.dober@gmail.com> wrote:

On 6/26/06, Dark Ambient <sambient@gmail.com> wrote:
> Robert,
>
> Thank you for a great explanation. I have a question or two and might
> have some more later :). The program is an assignment in a book
> "learn to program" which uses Ruby but is pretty much for beginners.
> While I've seen some of the of the other condition testers, (when, do,
> case, etc) the author sticks to the real basics, while, if, else and
> elsif. The author did write the program out, somewhat verbose and
> asked that it be re-written. Suprisingly, he said while he DOES NOT
> like to use "return", he might be forgiving if it was used in the

This is a very extreme point of view, like when I learnt Pascal in
university.

> re-write. Admitedly, your code is far cleaner and more to Matz's
> style of Ruby being almost like pseudo-code.
> So, question 1 - "loop do" seems like a great alternative to "while"

No loop do ... end or loop { } is the aequivaelent to
     while true do or while(true){ }
it is an endless loop.

> but could it be subsituted all the time when a loop is required ? or
> are there times when while has some unique ways of doing things ?
>
> You wrote:
> "surprisingly the example you chose, which is needed> about everywhere is
> not the easiest to implement".

> Question 2 - I'm not sure how to take this statement. To me in the
> context of programming it seems like a pretty basic function
> regardless of how one may master it but interested in why you chose
> the words you did ?

Because of the need to return from the middle of the loop

> Look forward to your responses.
>
> Thank you again!
> Stuart

H''s been a pleasure.
Cheers
Robert

> On 6/26/06, Robert Dober <robert.dober@gmail.com> wrote:
> > Hi ambient
> >
> > I will answer this off-list not because it was a bad thing of you to
answer
> > on list but just because you were unlucky with the anwsers :wink:
> >
> > First I will give you the code
> > def ask question
> > loop do ### this loops forever, and that's what we need because of
the
> > loosers :wink:
> >
> > puts question
> > case gets.chomp.downcase
> > when "yes"
> > return true
> > when "no"
> > return false
> > else
> > puts "Please kindly reply with \"yes\" or \"no\"
> > end
> > end
> > end
> >
> > Now some explanations, the most important trick is to write your code as
> > simple as possible, surprisingly the example you chose, which is needed
> > about everywhere is
> > not the easiest to implement, but local exits (in our case the "return"
can
> > be very helpful).
> >
> > So what did you want to do?
> > Ask the user a question
> > get a reply
> > return true or false if the reply is syntactically correct
> > Insult the looser :wink: in any other case and do it again
> >
> > As there is no looping construct which tests the looping condition after
the
> > first run of the loop body it is *normal* that your code gut clumpsy.
The
> > endless
> > loop do
> > end
> > or
> > loop {
> > }
> >
> > often helps to write clearer code, do not forget to break or return from
> > these loops though!!!
> >
> > In our case we want the method to return true or false anyway as soon as
the
> > input
> > is correct, so we kill to birds with one stone.
> >
> > The pseudo code above can be translated as follows
> >
> > loop do #### preparing for the potential need to reanswer the question
:wink:
> > puts question
> > case gets.chomp.downcase ### examine the reply
> > ### return true or false if the code is synt. correct
> > when "yes" ### greatinput is correct we return the
corresponding
> > value
> > return true ### returning from the method gets us out of
the
> > loop to :))
> > when "no" ### as above
> > return false
> > else ### Now we get to the insult part and loop back to the
question
> > puts "Please kindly reply with \"yes\" or \"no\""
> > end # case
> > end # loop
> >
> > Feel free 2 ask any more questions
> > Cheers
> > Robert
> >
>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

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

···

On 6/25/06, Rob Biedenharn <Rob@agileconsultingllc.com> wrote:

On Jun 25, 2006, at 9:32 AM, Dark Ambient 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 Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
+1 513-295-4739

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.

···

On Jun 25, 2006, at 14:45, Rob Biedenharn wrote:

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

while (not reply)
  if (reply !='yes' || reply != 'no' )
    puts ' Please answer "yes" or "no".'
  elsif reply == 'yes'
    reply = true
  else reply == 'no'
    reply = false
  end
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!

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 Mon, Jun 26, 2006 at 08:57:05AM +0900, Pete Yandell wrote:

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

OK, first I just *have* to ask: Do you have a copy of Programming Ruby?

No? Get the first edition here: Programming Ruby: The Pragmatic Programmer's Guide

keep reading...!

Alright, if there are any people remaining that have some patience to
repeat I'm running into the same problem again. And for now I really
want to stick to while,because now it's a real sticking point for me.
If I do nothing else in Ruby, mastering the while statement is a
must.:slight_smile:

So here I've created a method. See inline for why I think it should work.

#sort is the parameter for the alpha method
def alpha sort

#setting up my arrays
s_words =
u_words =

#assign a blank string to sort to start things off
sort = ' '

Why are you using sort as a parameter and then overwriting it here?!

# what I'm trying to say here is that if sort remains empty continue the loop
while sort == ' '
# to prompt the user to enter something I've added the puts statement
puts 'Please enter a word to be sorted'
#Now I'll assign sort to whatever the user inputs.
sort = gets.chomp.downcase
#Now I want to put the string into the array.
u_words.push['sort']

u_words << sort

you don't want 'sort' as that's a string with s, o, r, and t -- you want the value of the variable sort (which would be better named something like: word)

#I haven't thought it completely through but I'll probably want to
give the user a
#surrender word to stop the loop. Still I think at this point it
should loop at least
#once. Sadly, it does not, so either I'm thick or this is a hard
concept for me. #Polymorphism seems easier to grasp right now

perhaps an empty word?

end
end

TIA
Stuart

instead of s_words, just use u_words.sort

And while I'm at it, perhaps the method should be called "get_sorted_word_list" or something else a bit more descriptive that simply "alpha".

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com

···

On Jun 26, 2006, at 1:27 PM, Dark Ambient wrote:

On 6/26/06, Robert Dober <robert.dober@gmail.com> wrote:

On 6/26/06, Dark Ambient <sambient@gmail.com> wrote:
> Robert,
>
> Thank you for a great explanation. I have a question or two and might
> have some more later :). The program is an assignment in a book
> "learn to program" which uses Ruby but is pretty much for beginners.
> While I've seen some of the of the other condition testers, (when, do,
> case, etc) the author sticks to the real basics, while, if, else and
> elsif. The author did write the program out, somewhat verbose and
> asked that it be re-written. Suprisingly, he said while he DOES NOT
> like to use "return", he might be forgiving if it was used in the

This is a very extreme point of view, like when I learnt Pascal in
university.

> re-write. Admitedly, your code is far cleaner and more to Matz's
> style of Ruby being almost like pseudo-code.
> So, question 1 - "loop do" seems like a great alternative to "while"

No loop do ... end or loop { } is the aequivaelent to
     while true do or while(true){ }
it is an endless loop.

> but could it be subsituted all the time when a loop is required ? or
> are there times when while has some unique ways of doing things ?
>
> You wrote:
> "surprisingly the example you chose, which is needed> about everywhere is
> not the easiest to implement".

> Question 2 - I'm not sure how to take this statement. To me in the
> context of programming it seems like a pretty basic function
> regardless of how one may master it but interested in why you chose
> the words you did ?

Because of the need to return from the middle of the loop

> Look forward to your responses.
>
> Thank you again!
> Stuart

H''s been a pleasure.
Cheers
Robert

> On 6/26/06, Robert Dober <robert.dober@gmail.com> wrote:
> > Hi ambient
> >
> > I will answer this off-list not because it was a bad thing of you to
answer
> > on list but just because you were unlucky with the anwsers :wink:
> >
> > First I will give you the code
> > def ask question
> > loop do ### this loops forever, and that's what we need because of
the
> > loosers :wink:
> >
> > puts question
> > case gets.chomp.downcase
> > when "yes"
> > return true
> > when "no"
> > return false
> > else
> > puts "Please kindly reply with \"yes\" or \"no\"
> > end
> > end
> > end
> >
> > Now some explanations, the most important trick is to write your code as
> > simple as possible, surprisingly the example you chose, which is needed
> > about everywhere is
> > not the easiest to implement, but local exits (in our case the "return"
can
> > be very helpful).
> >
> > So what did you want to do?
> > Ask the user a question
> > get a reply
> > return true or false if the reply is syntactically correct
> > Insult the looser :wink: in any other case and do it again
> >
> > As there is no looping construct which tests the looping condition after
the
> > first run of the loop body it is *normal* that your code gut clumpsy.
The
> > endless
> > loop do
> > end
> > or
> > loop {
> > }
> >
> > often helps to write clearer code, do not forget to break or return from
> > these loops though!!!
> >
> > In our case we want the method to return true or false anyway as soon as
the
> > input
> > is correct, so we kill to birds with one stone.
> >
> > The pseudo code above can be translated as follows
> >
> > loop do #### preparing for the potential need to reanswer the question
:wink:
> > puts question
> > case gets.chomp.downcase ### examine the reply
> > ### return true or false if the code is synt. correct
> > when "yes" ### greatinput is correct we return the
corresponding
> > value
> > return true ### returning from the method gets us out of
the
> > loop to :))
> > when "no" ### as above
> > return false
> > else ### Now we get to the insult part and loop back to the
question
> > puts "Please kindly reply with \"yes\" or \"no\""
> > end # case
> > end # loop
> >
> > Feel free 2 ask any more questions
> > Cheers
> > Robert
> >
>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

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:

···

On 6/25/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

On Jun 25, 2006, at 14:45, Rob Biedenharn wrote:

> On Jun 25, 2006, at 9:32 AM, Dark Ambient wrote:
>
>> while (not reply)
>> if (reply !='yes' || reply != 'no' )
>> puts ' Please answer "yes" or "no".'
>> elsif reply == 'yes'
>> reply = true
>> else reply == 'no'
>> reply = false
>> end
>> 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!

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.

Hi --

···

On Mon, 26 Jun 2006, Cliff Cyphers wrote:

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

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

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 (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

See what the readers are saying about "Ruby for Rails"!

This is the while explanation (most of it) from PR 2nd edition , which I own.

while boolean-expression [ do | : ]
body
end
executes body zero or more times as long as boolean-expression is true.
until boolean-expression [ do | : ]
body
end

It doesn't help me one bit (literally), not with correctly setting up the loop.

Stuart

···

On 6/26/06, Rob Biedenharn <Rob@agileconsultingllc.com> wrote:

OK, first I just *have* to ask: Do you have a copy of Programming Ruby?

No? Get the first edition here: Ruby-Doc.org: Documenting the Ruby Language
ProgrammingRuby/

keep reading...!

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.

···

On Jun 25, 2006, at 16:16, Dark Ambient wrote:

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

···

On 6/25/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

On Mon, 26 Jun 2006, Cliff Cyphers wrote:

> On Mon, Jun 26, 2006 at 08:57:05AM +0900, Pete Yandell wrote:
>> 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
>>
>
> 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 (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

See what the readers are saying about "Ruby for Rails"!
http://www.rubypowerandlight.com/quotes

Your biggest problem in the code you put up is that you're using the same variable for several different things: a (apparently redundant) parameter to the method, a loop condition, and to hold user input - it's much better, especially when you're learning to program, to use separate variables for these separate concerns.

There are several problems with the code, one of which is (again) the bad choice of loop condition, observe your code stripped down to only the bits which affect the loop continuing or not:

sort = ''
while sort == ''
   sort = gets.etc.etc # sort != ''
end

So, at the end of the loop, sort != '', and the loop terminates. The answer (again) is to pick a loop condition that you know will be true as long as you want the loop to continue. This is pretty accurately described in the excerpt you posted - for the first loop, the condition is true, so the body executes. For the next iteration, the condition is false, so the loop body doesn't execute, and the program continues.

matthew smillie.

···

On Jun 26, 2006, at 19:26, Dark Ambient wrote:

On 6/26/06, Rob Biedenharn <Rob@agileconsultingllc.com> wrote:

OK, first I just *have* to ask: Do you have a copy of Programming Ruby?

No? Get the first edition here: Ruby-Doc.org: Documenting the Ruby Language
ProgrammingRuby/

keep reading...!

This is the while explanation (most of it) from PR 2nd edition , which I own.

while boolean-expression [ do | : ]
body
end
executes body zero or more times as long as boolean-expression is true.
until boolean-expression [ do | : ]
body
end

It doesn't help me one bit (literally), not with correctly setting up the loop.

Ok a 30w light bulb went off so now I see that I've changed the value
of sort and ended the loop, but, what I don't understand is if the
loop terminating or cycling is dependent on the user input then the
initialization of sort should match the gets call. Does my seemingly
convoluted thinking make sense here ? If I left sort alone in the
first 2 lines above, but then assigned another variable =
gets.....,then I won't know the user wants to quit.

Stuart

···

On 6/26/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

On Jun 26, 2006, at 19:26, Dark Ambient wrote:

Your biggest problem in the code you put up is that you're using the
same variable for several different things: a (apparently redundant)
parameter to the method, a loop condition, and to hold user input -
it's much better, especially when you're learning to program, to use
separate variables for these separate concerns.

There are several problems with the code, one of which is (again) the
bad choice of loop condition, observe your code stripped down to only
the bits which affect the loop continuing or not:

sort = ''
while sort == ''
   sort = gets.etc.etc # sort != ''
end

So, at the end of the loop, sort != '', and the loop terminates.

Sorry, meant to put this in the last reply. One thing I noticed is
that by removing the method definition I can get the loop to work. I
did change some of the verbage around though.
I commentd out the def method , and changed the end condition to
!='stop' but when I contain it in the method it no longer works.
Makes me wonder about methods.

#def sortwords

# s_words =
  #u_words =

word = ''
while word != 'stop'
  puts 'Please enter a word to be sorted'
  word = gets.chomp.downcase
  #u_words.push['sort']

#end

end

Stuart

···

On 6/26/06, Dark Ambient <sambient@gmail.com> wrote:

On 6/26/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:
> On Jun 26, 2006, at 19:26, Dark Ambient wrote:

> Your biggest problem in the code you put up is that you're using the
> same variable for several different things: a (apparently redundant)
> parameter to the method, a loop condition, and to hold user input -
> it's much better, especially when you're learning to program, to use
> separate variables for these separate concerns.
>
> There are several problems with the code, one of which is (again) the
> bad choice of loop condition, observe your code stripped down to only
> the bits which affect the loop continuing or not:
>
> sort = ''
> while sort == ''
> sort = gets.etc.etc # sort != ''
> end
>
> So, at the end of the loop, sort != '', and the loop terminates.

Ok a 30w light bulb went off so now I see that I've changed the value
of sort and ended the loop, but, what I don't understand is if the
loop terminating or cycling is dependent on the user input then the
initialization of sort should match the gets call. Does my seemingly
convoluted thinking make sense here ? If I left sort alone in the
first 2 lines above, but then assigned another variable =
gets.....,then I won't know the user wants to quit.

Stuart

Sorry, meant to put this in the last reply. One thing I noticed is
that by removing the method definition I can get the loop to work. I
did change some of the verbage around though.
I commentd out the def method , and changed the end condition to
!='stop' but when I contain it in the method it no longer works.
Makes me wonder about methods.

Are you calling the method? Or just defining it? This defines a method:

def sortwords
   u_words =
   word = ''
   while word != 'stop'
     puts "enter a word"
     word = gets.chomp.downcase
     u_word.push[word]
   end
   u_words.sort
end

This actually calls/executes it:

sortwords # (input 'foo', 'bar', 'baz', 'stop')
=> ["bar", "baz", "foo", "stop"]

You'll notice that you get the 'stop' on the end of the array, which probably isn't what you want.

If I left sort alone in the
first 2 lines above, but then assigned another variable =
gets.....,then I won't know the user wants to quit.

Unless... you check THAT variable. Maybe like this:

def sortwords
   words =
   continue = false
   while continue
     word = gets.chomp.downcase
     if word == 'stop'
       continue = false
     elsif word == 'hello'
       # or some other special case.
       puts "hello yourself"
     else
       # default behaviour
       words.push(word)
     end
   end
   return words.sort
end

sortwords # (input 'foo', 'bar', 'baz', 'stop')
=> ["bar", "baz", "foo"]

matthew smillie.

···

On Jun 26, 2006, at 20:24, Dark Ambient wrote:

I finally have had more success, at least for the first part of the
exercise. Thanks for all the help. I do have another question (will
they ever stop) - in my code below as in Matthew's example the
array.push doesn't take place till after the loop is exited. Why is
that, can't they be added incrementally ? I did the array.push in the
loop and it completely skipped over it, or seemed to at least.

def sort words

  u_words =
  s_words =

  continue = true
  while continue
  puts words
  userword = gets.chomp.downcase
  u_words.push(userword)
  puts 'we now have these words in our list '
  puts u_words
  puts 'shall we continue?'
  a = gets.chomp.downcase
    if a == 'yes'
      continue = true
            else
              continue = false
            end
            puts 'we now have these words in our list '
  puts u_words
    end
end
  sort 'Please enter a word for sorting'

I have a ways to go to complete this little tiny project but I must
not use array.sort.

Stuart

···

On 6/26/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

On Jun 26, 2006, at 20:24, Dark Ambient wrote:

def sortwords
   words =
   continue = false
   while continue
     word = gets.chomp.downcase
     if word == 'stop'
       continue = false
     elsif word == 'hello'
       # or some other special case.
       puts "hello yourself"
     else
       # default behaviour
       words.push(word)
     end
   end
   return words.sort
end

sortwords # (input 'foo', 'bar', 'baz', 'stop')
=> ["bar", "baz", "foo"]

matthew smillie.

I finally have had more success, at least for the first part of the
exercise. Thanks for all the help. I do have another question (will
they ever stop) - in my code below as in Matthew's example the
array.push doesn't take place till after the loop is exited. Why is
that, can't they be added incrementally ? I did the array.push in the
loop and it completely skipped over it, or seemed to at least.

def sort words

  u_words =
  s_words =

  continue = true
  while continue
  puts words
  userword = gets.chomp.downcase
  u_words.push(userword)
  puts 'we now have these words in our list '
  puts u_words
  puts 'shall we continue?'
  a = gets.chomp.downcase
    if a == 'yes'
      continue = true
            else
              continue = false
            end
            puts 'we now have these words in our list '
  puts u_words
    end
end
  sort 'Please enter a word for sorting'

# Always try to keep your code simple
loop {
    puts words
    userword = gets.chomp.downcase
    break if userword == "stop"
    u_words << userwords
}
# I understand that you have to implement your sorting algorithm yourself,
that is
# a very good exercise.
mysort( u_words )
^^^^^^^ yes, you are going to write this!

Here is how to go for it

use bubble sort or insertion sort (the later is much better).
Stay away from the sophisticated algorithms for now.

Never forget what the ancient Greeks said:
    Learning is Suffering.

Hang in there

Robert

···

On 6/27/06, Dark Ambient <sambient@gmail.com> wrote:

I have a ways to go to complete this little tiny project but I must
not use array.sort.

Stuart

On 6/26/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:
> On Jun 26, 2006, at 20:24, Dark Ambient wrote:

> def sortwords
> words =
> continue = false
> while continue
> word = gets.chomp.downcase
> if word == 'stop'
> continue = false
> elsif word == 'hello'
> # or some other special case.
> puts "hello yourself"
> else
> # default behaviour
> words.push(word)
> end
> end
> return words.sort
> end
>
> sortwords # (input 'foo', 'bar', 'baz', 'stop')
> => ["bar", "baz", "foo"]
>
> matthew smillie.
>

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein