Help with while condition OR condition

Discussion in 'Ruby' started by Bill W., May 7, 2011.

  1. Bill W.

    Bill W. Guest

    Hi everyone,

    This is my first post, so I hope I don't sound too inexperienced..

    I'm trying to teach myself Ruby, and have run into an issue with a while
    statement that will break if an input is "exit" or "quit".
    As of right now, it works if exit is input, but not quit

    I know I am completely misusing the entire thing, but here is what I
    came up with:

    EXIT = "exit" #need constants since Ruby gets pissed at string literals
    QUIT = "quit" #in a comparison

    print "Input: "
    input = gets
    while input.chomp.downcase != (EXIT || QUIT) #only works for exit

    #Do something

    print "Input: " #pick up the next input and check it
    input = gets
    end

    I know that Ruby has a lot of shortcuts, but if you post any please
    explain how they work (or provide a link to a good explanation.

    Thanks!

    --
    Posted via http://www.ruby-forum.com/.
     
    Bill W., May 7, 2011
    #1
    1. Advertising

  2. [Note: parts of this message were removed to make it a legal post.]

    Don't do that, just use eql?

    begin
    print "input: "
    input = gets.chomp.downcase
    end while not (input.eql? "exit" or input.eql? "quit")
     
    Steve Klabnik, May 7, 2011
    #2
    1. Advertising

  3. On Saturday, May 7, 2011, Bill W. <> wrote:
    > Hi everyone,
    >
    > This is my first post, so I hope I don't sound too inexperienced..
    >
    > I'm trying to teach myself Ruby, and have run into an issue with a while
    > statement that will break if an input is "exit" or "quit".
    > As of right now, it works if exit is input, but not quit
    >
    > I know I am completely misusing the entire thing, but here is what I
    > came up with:
    >
    > EXIT =3D "exit" =C2=A0#need constants since Ruby gets pissed at string li=

    terals
    > QUIT =3D "quit" =C2=A0#in a comparison
    >
    > print "Input: "
    > input =3D gets
    > while input.chomp.downcase !=3D (EXIT || QUIT) #only works for exit


    The || operator returns the operand on the left if it is "true-ish"
    (anything other than nil or false), otherwise it evaluates and returns
    the operand on the right. So (EXIT || QUIT) where EXIT=3D"exit" just
    evaluates to "exit".

    You could do this with the || between two comparisons (rather than two
    options in one comparison).

    Also, Ruby has no problem with comparisons against string literals;
    what made you think it did?
     
    Christopher Dicely, May 7, 2011
    #3
  4. This line doesn't behave in the way I think you expect:

    > while input.chomp.downcase !=3D (EXIT || QUIT) #only works for exit


    This says, "check if the downcased input is not equal to the value of
    the expression `EXIT || QUIT`". What is the value of that expression?
    In this case, it will resolve to EXIT, since the string "exit" is not
    false or nil and is thus true. The value of QUIT is never evaluated.
    So, if the input is not equal to exit, the while loop continues.

    Why is that? In Ruby, all expressions have both a "value" and a
    "truthiness". An expression is "falsy" if it evaluates to either
    `false` or `nil`; otherwise it is `truthy`. In the case of an
    expression like `foo || bar`, the truth table would look like this:

    * foo is truthy, bar is truthy: result is `foo` and truthy
    * foo is truthy, bar is falsy: result is `foo` and truthy
    * foo is falsy, bar is truthy: result is `bar` and truthy
    * foo is falsy, bar is falsy: result is `bar` and falsy

    So you can see that in your case, foo is EXIT and bar is QUIT, both of
    which are truthy values; thus the expression is "exit". To get what
    you what want, try something like this:

    command =3D input.chomp.downcase
    while command !=3D "exit" || command !=3D "quit" ...

    Or, more succinctly:

    case command
    when "exit", "quit"
    puts "exiting!"; ...
    else
    # do stuff
    end

    ~ jf
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/



    On Sat, May 7, 2011 at 18:37, Bill W. <> wrote:
    > Hi everyone,
    >
    > This is my first post, so I hope I don't sound too inexperienced..
    >
    > I'm trying to teach myself Ruby, and have run into an issue with a while
    > statement that will break if an input is "exit" or "quit".
    > As of right now, it works if exit is input, but not quit
    >
    > I know I am completely misusing the entire thing, but here is what I
    > came up with:
    >
    > EXIT =3D "exit" =C2=A0#need constants since Ruby gets pissed at string li=

    terals
    > QUIT =3D "quit" =C2=A0#in a comparison
    >
    > print "Input: "
    > input =3D gets
    > while input.chomp.downcase !=3D (EXIT || QUIT) #only works for exit
    >
    > =C2=A0#Do something
    >
    > print "Input: " =C2=A0#pick up the next input and check it
    > input =3D gets
    > end
    >
    > I know that Ruby has a lot of shortcuts, but if you post any please
    > explain how they work (or provide a link to a good explanation.
    >
    > Thanks!
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
     
    John Feminella, May 7, 2011
    #4
  5. Oops, small typo:

    while command !=3D "exit" || command !=3D "quit" ...

    should be:

    while command !=3D "exit" && command !=3D "quit" ...
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/



    On Sat, May 7, 2011 at 18:53, John Feminella <> wrote:
    > This line doesn't behave in the way I think you expect:
    >
    >> while input.chomp.downcase !=3D (EXIT || QUIT) #only works for exit

    >
    > This says, "check if the downcased input is not equal to the value of
    > the expression `EXIT || QUIT`". What is the value of that expression?
    > In this case, it will resolve to EXIT, since the string "exit" is not
    > false or nil and is thus true. The value of QUIT is never evaluated.
    > So, if the input is not equal to exit, the while loop continues.
    >
    > Why is that? In Ruby, all expressions have both a "value" and a
    > "truthiness". An expression is "falsy" if it evaluates to either
    > `false` or `nil`; otherwise it is `truthy`. In the case of an
    > expression like `foo || bar`, the truth table would look like this:
    >
    > * foo is truthy, bar is truthy: result is `foo` and truthy
    > * foo is truthy, bar is falsy: result is `foo` and truthy
    > * foo is falsy, bar is truthy: result is `bar` and truthy
    > * foo is falsy, bar is falsy: result is `bar` and falsy
    >
    > So you can see that in your case, foo is EXIT and bar is QUIT, both of
    > which are truthy values; thus the expression is "exit". To get what
    > you what want, try something like this:
    >
    > =C2=A0 =C2=A0command =3D input.chomp.downcase
    > =C2=A0 =C2=A0while command !=3D "exit" || command !=3D "quit" ...
    >
    > Or, more succinctly:
    >
    > =C2=A0 =C2=A0case command
    > =C2=A0 =C2=A0when "exit", "quit"
    > =C2=A0 =C2=A0 =C2=A0puts "exiting!"; ...
    > =C2=A0 =C2=A0else
    > =C2=A0 =C2=A0 =C2=A0# do stuff
    > =C2=A0 =C2=A0end
    >
    > ~ jf
    > --
    > John Feminella
    > Principal Consultant, BitsBuilder
    > LI: http://www.linkedin.com/in/johnxf
    > SO: http://stackoverflow.com/users/75170/
    >
    >
    >
    > On Sat, May 7, 2011 at 18:37, Bill W. <> wrote:
    >> Hi everyone,
    >>
    >> This is my first post, so I hope I don't sound too inexperienced..
    >>
    >> I'm trying to teach myself Ruby, and have run into an issue with a while
    >> statement that will break if an input is "exit" or "quit".
    >> As of right now, it works if exit is input, but not quit
    >>
    >> I know I am completely misusing the entire thing, but here is what I
    >> came up with:
    >>
    >> EXIT =3D "exit" =C2=A0#need constants since Ruby gets pissed at string l=

    iterals
    >> QUIT =3D "quit" =C2=A0#in a comparison
    >>
    >> print "Input: "
    >> input =3D gets
    >> while input.chomp.downcase !=3D (EXIT || QUIT) #only works for exit
    >>
    >> =C2=A0#Do something
    >>
    >> print "Input: " =C2=A0#pick up the next input and check it
    >> input =3D gets
    >> end
    >>
    >> I know that Ruby has a lot of shortcuts, but if you post any please
    >> explain how they work (or provide a link to a good explanation.
    >>
    >> Thanks!
    >>
    >> --
    >> Posted via http://www.ruby-forum.com/.
    >>
    >>

    >
     
    John Feminella, May 7, 2011
    #5
  6. On 05/07/2011 03:37 PM, Bill W. wrote:
    > Hi everyone,
    >
    > This is my first post, so I hope I don't sound too inexperienced..
    >
    > I'm trying to teach myself Ruby, and have run into an issue with a while
    > statement that will break if an input is "exit" or "quit".
    > As of right now, it works if exit is input, but not quit
    >
    > I know I am completely misusing the entire thing, but here is what I
    > came up with:
    >
    > EXIT = "exit" #need constants since Ruby gets pissed at string literals
    > QUIT = "quit" #in a comparison
    >
    > print "Input: "
    > input = gets
    > while input.chomp.downcase != (EXIT || QUIT) #only works for exit


    It can help to take apart expressions in irb (interactive ruby):

    $ irb
    >> EXIT = "exit"

    => "exit"
    >> QUIT = "quit"

    => "quit"
    >> EXIT || QUIT

    => "exit"
    >> "quit" == (EXIT || QUIT)

    => false

    > #Do something
    >
    > print "Input: " #pick up the next input and check it
    > input = gets
    > end
    >
    > I know that Ruby has a lot of shortcuts, but if you post any please
    > explain how they work (or provide a link to a good explanation.


    Something to tinker with:

    print "Input: "
    while input = gets
    case s = input.chomp.downcase
    when "exit", "quit"
    puts "You wanted to #{s} this mighty fine program?"
    break
    else
    puts "Why do you say '#{s}'?"
    print "Input: "
    end
    end
    puts "Done."
     
    Joel VanderWerf, May 7, 2011
    #6
  7. Bill W.

    Hashmal Guest

    `(EXIT || QUIT)` will always return "exit" as EXIT is never `nil` or
    `false`, so in your case, the input string is never checked against `QUIT`.

    Try this:

    print "Input: "
    input = gets

    until ["exit", "quit"].include? input.chomp.downcase
    # Do something
    print "Input: "
    input = gets
    end

    As you can see you can do it without constants. the method `include?`
    checks if an element exists in the array. `until` is basically an
    inverted `while`.



    On 5/8/11 12:37 AM, Bill W. wrote:
    > Hi everyone,
    >
    > This is my first post, so I hope I don't sound too inexperienced..
    >
    > I'm trying to teach myself Ruby, and have run into an issue with a while
    > statement that will break if an input is "exit" or "quit".
    > As of right now, it works if exit is input, but not quit
    >
    > I know I am completely misusing the entire thing, but here is what I
    > came up with:
    >
    > EXIT = "exit" #need constants since Ruby gets pissed at string literals
    > QUIT = "quit" #in a comparison
    >
    > print "Input: "
    > input = gets
    > while input.chomp.downcase != (EXIT || QUIT) #only works for exit
    >
    > #Do something
    >
    > print "Input: " #pick up the next input and check it
    > input = gets
    > end
    >
    > I know that Ruby has a lot of shortcuts, but if you post any please
    > explain how they work (or provide a link to a good explanation.
    >
    > Thanks!
    >
     
    Hashmal, May 8, 2011
    #7
  8. Bill W.

    Bill W. Guest

    Wow! I would say this is the most replies I have ever had on a
    programming topic!

    Thanks for the in-depth description of how || works, I was WAY off.

    I tried this with until already once, but I had the rest of it wrong and
    it failed.

    command = input.chomp.downcase
    until ["exit", "quit"].include? input.chomp.downcase
    are both exactly the type of shortcuts i would have never though of!

    Thanks again!

    --
    Posted via http://www.ruby-forum.com/.
     
    Bill W., May 8, 2011
    #8
  9. Bill W.

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Sat, May 7, 2011 at 5:37 PM, Bill W. <> wrote:

    >
    > EXIT = "exit" #need constants since Ruby gets pissed at string literals
    > QUIT = "quit" #in a comparison
    >
    >

    It doesn't get pissed at string literals in comparison, its just that it was
    able to tell that the way you were comparing didn't make sense (because
    string literal is known at time you wrote it, not dynamically looked up, so
    the comparison is also known, and doesn't make sens). So it was warning you
    of the issue. It didn't complain when you stored then in vars/constants,
    because it doesn't know their value until runtime. They could hypothetically
    be false or nil, so it isn't conspicuously an error.

    e.g.

    if "some literal"
    # do something
    end # !> string literal in condition

    if "some literal" || "other"
    # do something
    end # !> string literal in condition
     
    Josh Cheek, May 8, 2011
    #9
  10. Bill W.

    7stud -- Guest

    Hi,

    A lot of beginners make the same mistake you did. 'Compound
    conditionals' have to be written like separate conditionals and then
    hooked together with an 'or' or 'and'. For instance if you wanted to do
    something only if a number were greater than 5 and less then 10, you
    would do this:

    x > 5
    x < 10
    and

    if x > 5 and x < 10
    #do something
    end

    Everyone should use 'and' and 'or' by default instead of && and ||.
    Code reads better that way. Only if you have a specific reason to,
    should you use && or ||.

    Good luck.

    --
    Posted via http://www.ruby-forum.com/.
     
    7stud --, May 8, 2011
    #10
  11. > Everyone should use 'and' and 'or' by default instead of && and ||.
    > Code reads better that way. =C2=A0Only if you have a specific reason to,
    > should you use && or ||.


    It's not a good idea to make a blanket rule like that, imo. The "and"
    keyword is not really a substitute for "&&", since it has different
    precedence. It's best viewed as a control flow modifier (like "if" or
    "unless" when at the end of an expression), rather than a true logical
    operator.

    If you don't know that it's not quite the same, this can get you into
    big trouble by leading to subtle bugs. Consider this code, for
    instance:

    >> missiles_armed =3D true

    =3D> true
    >> go_for_launch =3D false

    =3D> false

    # Using &&
    >> go_for_launch && missiles_armed ? :fire_ze_missiles : :abort_launch

    =3D> :abort_launch # Looks good here.

    # Using "and"
    >> go_for_launch and missiles_armed ? :fire_ze_missiles : :abort_launch

    =3D> false # Uh-oh! We didn't get the `:abort_launch` we were expecting...

    ~ jf
    --
    John Feminella
    Principal Consultant, BitsBuilder
    LI: http://www.linkedin.com/in/johnxf
    SO: http://stackoverflow.com/users/75170/



    On Sat, May 7, 2011 at 22:29, 7stud -- <> wrote:
    > Hi,
    >
    > A lot of beginners make the same mistake you did. =C2=A0 'Compound
    > conditionals' have to be written like separate conditionals and then
    > hooked together with an 'or' or 'and'. =C2=A0For instance if you wanted t=

    o do
    > something only if a number were greater than 5 and less then 10, you
    > would do this:
    >
    > x > 5
    > x < 10
    > and
    >
    > if x > 5 and x < 10
    > =C2=A0#do something
    > end
    >
    > Everyone should use 'and' and 'or' by default instead of && and ||.
    > Code reads better that way. =C2=A0Only if you have a specific reason to,
    > should you use && or ||.
    >
    > Good luck.
    >
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >
     
    John Feminella, May 8, 2011
    #11
  12. 7stud -- wrote in post #997311:
    > In ruby, everyone should use 'and' and 'or' by default instead of && and
    > ||.


    I would advise exactly the opposite: there are many traps for the unwary
    if you use 'and' and 'or'. Two prime examples:

    >> val = 10

    => 10
    >> ok = val < 3 or val > 5

    => true
    >> ok

    => false

    >> a = true

    => true
    >> b = not a

    SyntaxError: compile error
    (irb):7: syntax error, unexpected kNOT

    Use '||' and '!' respectively and you won't have a problem.

    --
    Posted via http://www.ruby-forum.com/.
     
    Brian Candler, May 8, 2011
    #12
  13. Bill W.

    7stud -- Guest

    Brian Candler wrote in post #997379:
    >
    > Use '||' and '!' respectively and you won't have a problem.
    >


    lol.

    --
    Posted via http://www.ruby-forum.com/.
     
    7stud --, May 9, 2011
    #13
  14. On Mon, May 9, 2011 at 10:11 PM, 7stud -- <> wrote:
    > Brian Candler wrote in post #997379:
    >>
    >> Use '||' and '!' respectively and you won't have a problem.
    >>

    >
    > lol.


    Should've tried the code first:

    irb(main):001:0> val = 10
    => 10
    irb(main):002:0> ok = val < 3 || val > 5
    => true
    irb(main):003:0> ok
    => true
    irb(main):004:0> a = true
    => true
    irb(main):005:0> b = !a
    => false

    Using *only* "or" or "not" obviously doesn't lead to the expected
    results, while using || and ! do.

    --
    Phillip Gawlowski

    Though the folk I have met,
    (Ah, how soon!) they forget
    When I've moved on to some other place,
    There may be one or two,
    When I've played and passed through,
    Who'll remember my song or my face.
     
    Phillip Gawlowski, May 9, 2011
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Daniel

    while condition

    Daniel, May 20, 2005, in forum: VHDL
    Replies:
    7
    Views:
    3,549
    Ralf Hildebrandt
    May 23, 2005
  2. -
    Replies:
    12
    Views:
    714
    Remon van Vliet
    Jun 15, 2005
  3. Claudio Grondi
    Replies:
    16
    Views:
    494
    Matimus
    Aug 30, 2006
  4. Sorin Schwimmer
    Replies:
    1
    Views:
    264
    Claudio Grondi
    Aug 28, 2006
  5. techi_C
    Replies:
    2
    Views:
    1,491
    Richard Bos
    Aug 10, 2006
Loading...

Share This Page