I posted a question a week or so now which I got some great help with.
Here I am again I'm afraid! What I am now struggling with is how to add
help. What I want is if the user gets the input wrong three times, I'd
like to print to print
Press 'h' for help
h
You must enter your age as two digits. i.e if you are twenty five, type 25.
here is the original method:
···
-----------------------------------------------
def check_age
print "Please enter your age: "
age = gets.chomp
target = 18..30
valid = /^\d{2}/
if valid.match(age)
if target === age.to_i
puts 'Have a nice holiday!'
elsif age.to_i < 18
puts 'Sorry, too young.'
elsif age.to_i > 30
puts 'Sorry, too old.'
end
else
puts 'Incorrect input.'
puts
check_age # Try again
end
end
Should I create a class and add a 'show_help' method (putting the
'check_age' method in there as well)? If so, how/where do I call that
method? The method in the above code calls itself. I am a complete
programming newbie by the way.
Maybe we could expand this program to help other new programmers like
myself? The jukebox example in Pickaxe2 seems to fizzle out.
My suggestion would be to add that behavior right when you are getting
the user input. Add a check at the beggining, and keep it out if the
if statement.
Also, I would change the if/elsif statements to a case statement. The
case statement is perfect for what you are trying to do.
Dan
···
On 7/18/06, simonh <simonharrison@fastmail.co.uk> wrote:
I posted a question a week or so now which I got some great help with.
Here I am again I'm afraid! What I am now struggling with is how to add
help. What I want is if the user gets the input wrong three times, I'd
like to print to print
> Press 'h' for help
> h
> You must enter your age as two digits. i.e if you are twenty five, type 25.
here is the original method:
-----------------------------------------------
def check_age
print "Please enter your age: "
age = gets.chomp
target = 18..30
valid = /^\d{2}/
if valid.match(age)
if target === age.to_i
puts 'Have a nice holiday!'
elsif age.to_i < 18
puts 'Sorry, too young.'
elsif age.to_i > 30
puts 'Sorry, too old.'
end
else
puts 'Incorrect input.'
puts
check_age # Try again
end
end
Should I create a class and add a 'show_help' method (putting the
'check_age' method in there as well)? If so, how/where do I call that
method? The method in the above code calls itself. I am a complete
programming newbie by the way.
Maybe we could expand this program to help other new programmers like
myself? The jukebox example in Pickaxe2 seems to fizzle out.
First, as Daniel already said, why not put the information right in the
loop? However, don't go recursive there, I'd do a loop instead:
age = 0
target_age = 30..65 #
while ! target === age
print "Please enter your age: (as two digits): "
result = gets
age = result.chomp.to_i
case age
when age < 30
puts 'Sorry, too young.'
when age > 75
puts 'Sorry, too old.'
else
puts 'Hava a nice holiday!'
return age
end
puts "Remember, age must be entered as two digits, e.g. 35"
end
Thanks for replies. Just to point out, this code is not meant for
anything in particular, just an example to help me learn ruby. I wanted
to understand recursion better which I now do. Also to understand
ranges and if statements too. What I'm trying to do here is understand
how to branch inside a method.
What are the benefits of using case instead of if? I was going to look
at case a bit later on. The commented code below is what I've tried but
it does not work too well. if i type 21 its says 'have a nice holiday!'
then 'Incorrect Input' and prompts me again.
···
-----------------------------------------------------------------------
def check_age
print "Please enter your age (or type 'h' for help): "
age = gets.chomp
target = 18..30
valid = /^\d{2}/
# if age == 'h'
# puts
# puts "Example: if you are twenty five, type 25"
# puts
# check_age #end
if valid.match(age)
if target === age.to_i
puts 'Have a nice holiday!'
elsif age.to_i < 18
puts 'Sorry, too young.'
elsif age.to_i > 30
puts 'Sorry, too old.'
end
else
puts "Incorrect input."
puts
check_age # Try again
end
end
First, as Daniel already said, why not put the information right in the
loop? However, don't go recursive there, I'd do a loop instead:
age = 0
target_age = 30..65 #
while ! target === age
s/target/target_age/ Also, "until" is a nicer way to do while ! .
print "Please enter your age: (as two digits): "
result = gets
age = result.chomp.to_i
No need to chomp:
age = gets.to_i
case age
when age < 30
Hang on.... Remember that a case statement works like this:
case a
when b
is equivalent to:
if b === a
So what you've got is:
if (age < 30) === age
which is going to be either:
if true === age
or
if false === age
Neither of those is ever true when age is an integer, so the test will
never succeed.
A simple if construct will work fine:
if age < 30
...
elsif age > 75
...
else
...
end
puts 'Sorry, too young.'
when age > 75
puts 'Sorry, too old.'
else
puts 'Hava a nice holiday!'
return age
end
puts "Remember, age must be entered as two digits, e.g. 35"
end
decided to have a go at using the case statement. Why won't this work?
···
-------------------------------------------------------------------------------------
def double_it
print "Please enter a whole number (or type 'h' for help) : "
num = gets.chomp
case num
when num == 'h'
puts
puts "A whole number is 45 for example, or 12564."
puts
when num.to_i > 1
num * num
print num.to_s
when num.to_i <= 0
puts "The number must be positive!"
end
end
double_it
gets
--------------------------------------------------------------------------------------
decided to have a go at using the case statement. Why won't this work?
-------------------------------------------------------------------------------------
def double_it
print "Please enter a whole number (or type 'h' for help) : "
num = gets.chomp
case num
when num == 'h'
puts
puts "A whole number is 45 for example, or 12564."
puts
when num.to_i > 1
num * num
What's that for?
print num.to_s
when num.to_i <= 0
puts "The number must be positive!"
end
end
double_it
gets
Do you really mean to end with gets?
As for the case statement: have a look at my previous post in this
thread. The problem is that you're comparing:
num
with the expression:
num == 'h'
Then you're comparing it with the expression "num.to_i > 1", and so
on.
A case statement isn't a good fit here; I'd just use if/else/.../end.
There are two forms of case block and you have sort of mixed them up. Either of the following defs of double_it will work. I think the first, using a case without a target, is probably what you want, but the second, a case with a target (compares target to pattern with ===), can be made to work, too.
Hope this helps.
def double_it
print "Please enter a whole number (or type 'h' for help) : "
num = gets.chomp
case
when num == 'h'
puts "A whole number is 45 for example, or 12564."
double_it
when (n = num.to_i) > 1
puts n * 2 # doubling not squaring
else
puts "Input must be positive number!"
double_it
end
end
double_it
print "Press any key to exit: "
STDIN.getc
def double_it
print "Please enter a whole number (or type 'h' for help) : "
num = gets.chomp
case num
when 'h'
puts "A whole number is 45 for example, or 12564."
double_it
when /^[^-]\d+/
puts num.to_i * 2 # doubling not squaring
else
puts "Input must be positive number!"
double_it
end
end
double_it
print "Press any key to exit: "
STDIN.getc
Regards, Morton
···
On Jul 19, 2006, at 5:05 AM, simonh wrote:
decided to have a go at using the case statement. Why won't this work?
-------------------------------------------------------------------------------------
def double_it
print "Please enter a whole number (or type 'h' for help) : "
num = gets.chomp
case num
when num == 'h'
puts
puts "A whole number is 45 for example, or 12564."
puts
when num.to_i > 1
num * num
print num.to_s
when num.to_i <= 0
puts "The number must be positive!"
end
end
double_it
gets
--------------------------------------------------------------------------------------
Thanks David. Great book by the way. Easier for a beginner than
pickaxe. Ever considered writing a 'Ruby Projects' book. Start with
some simple program ideas and build them up to something useful?
Demonstrating all the syntax/conventions of Ruby. I'm happy to put down
a deposit!
Anyway,
> case age
> when age < 30
Hang on.... Remember that a case statement works like this:
case a
when b
is equivalent to:
if b === a
So what you've got is:
if (age < 30) === age
which is going to be either:
if true === age
or
if false === age
Neither of those is ever true when age is an integer, so the test will
never succeed.
I don't quite understand I'm afraid. I have a variable I want to check
a number of conditions against. Can't i do this with the case
expression? Further explanation would be greatly appreciated.
A simple if construct will work fine:
if age < 30
...
elsif age > 75
...
else
...
end
Thats what I thought! What is the main advantage of case over if? Or
when would you be more likely to use one than the other?
> puts 'Sorry, too young.'
> when age > 75
> puts 'Sorry, too old.'
> else
> puts 'Hava a nice holiday!'
> return age
> end
> puts "Remember, age must be entered as two digits, e.g. 35"
> end
>
> check_age
No such method
I tried wrapping that code in a method and got an error. The main thing
I am trying to understand is where to put the code to print out help.
There are two forms of case block and you have sort of mixed them up. Either of the following defs of double_it will work. I think the first, using a case without a target, is probably what you want, but the second, a case with a target (compares target to pattern with ===), can be made to work, too.
That's a more thorough answer than mine, since I didn't think of the
non-targeted case. But I realize that I never think of it, because
I'm not clear on what its advantages are over a bunch of ifs. I guess
with multiple things you can do:
I view case without a target as a fancy, more compact, and (IMHO) more readable if-elsif-else block. Because it is more compact and more readable, I prefer it to if-elsif-else and tend to favor it. I may be influenced by some years of doing Common Lisp programming -- I was quite fond of cond.
Regards, Morton
···
On Jul 19, 2006, at 6:42 AM, dblack@wobblini.net wrote:
Hi --
On Wed, 19 Jul 2006, Morton Goldberg wrote:
There are two forms of case block and you have sort of mixed them up. Either of the following defs of double_it will work. I think the first, using a case without a target, is probably what you want, but the second, a case with a target (compares target to pattern with ===), can be made to work, too.
That's a more thorough answer than mine, since I didn't think of the
non-targeted case. But I realize that I never think of it, because
I'm not clear on what its advantages are over a bunch of ifs. I guess
with multiple things you can do:
I view case without a target as a fancy, more compact, and (IMHO) more readable if-elsif-else block. Because it is more compact and more readable, I prefer it to if-elsif-else and tend to favor it. I may be influenced by some years of doing Common Lisp programming -- I was quite fond of cond.
I'm not sure about its being more compact, unless you've got multiple
conditions in one when. Compare:
if a == 1
...
elsif a == 2
...
else
...
end
with:
case
when a == 1
...
when a == 2
...
else
...
end
In any, ummmm, case... I'm glad to be reminded of it. Do you use
it when things get more deeply nested?
David
···
On Wed, 19 Jul 2006, Morton Goldberg wrote:
On Jul 19, 2006, at 6:42 AM, dblack@wobblini.net wrote:
Hi --
On Wed, 19 Jul 2006, Morton Goldberg wrote:
There are two forms of case block and you have sort of mixed them up. Either of the following defs of double_it will work. I think the first, using a case without a target, is probably what you want, but the second, a case with a target (compares target to pattern with ===), can be made to work, too.
That's a more thorough answer than mine, since I didn't think of the
non-targeted case. But I realize that I never think of it, because
I'm not clear on what its advantages are over a bunch of ifs. I guess
with multiple things you can do:
fr morton:
# I view case without a target as a fancy, more compact, and (IMHO)
# more readable if-elsif-else block. Because it is more compact and
# more readable, I prefer it to if-elsif-else and tend to favor it. I
# may be influenced by some years of doing Common Lisp
me, too. if i ever need an elsif, i'd go then for the case block. i never did liked the "elsif" keyword (reminds me too of *nix scripts w if-fi blocks :). but that is just me
print 'white'
when blue
print 'blue'
when orange
print 'orange'
end
instead of
var = favourite_colour
if white
print 'white'
elsif blue
print 'blue'
...
end
In the second example you're not testing var; you're just testing
the values white and blue. So it's hard to compare it to the case
statement.
A case statement is basically a wrapper for a bunch of "if" tests --
but the wrapper has very specific behavior: it runs the === method on
each term in succession, with the cased object as the argument:
case a
when b # if b === a
...
when c,d # if (c === a) || (d === a)
etc.
When you're doing a comparison that doesn't have a === equivalent,
you'll generally need a plain "if".
I try (not always successfully) to avoid deeply nested constructs. When I can't escape nesting, rather than directly nesting, I favor writing something like:
def case_A
case
when ...
end
end
def case_B
case
when ...
end
end
case
when condition_A then case_A
when condition_B then case_B
end
Regards, Morton
···
On Jul 19, 2006, at 7:06 AM, dblack@wobblini.net wrote:
In any, ummmm, case... I'm glad to be reminded of it. Do you use
it when things get more deeply nested?
fr david:
# I'm not sure about its being more compact, unless you've got multiple
# conditions in one when. Compare:
#
# if a == 1
# ...
# elsif a == 2
# ...
# else
# ...
# end
#
# with:
#
# case
# when a == 1
# ...
# when a == 2
# ...
# else
# ...
# end
when i use it, i think more in "blocks". it's like "there's a case i'm handling, and the conditions are...".
# In any, ummmm, case... I'm glad to be reminded of it. Do you use
# it when things get more deeply nested?
i combine it w if-else (no elsif)
Here's another interesting usage (with target, but sort of in the
non-targeted spirit):
a = 1
case false
when a == 1
puts "a is not 1"
when a == 2
puts "a is not 2"
end
I imagine that would get some readability complaints... But I
kind of like it because once you get "false" in your head it's easier
to follow, possibly, than a lot of unless/! stuff.
fr david:
# Here's another interesting usage (with target, but sort of in the
# non-targeted spirit):
···
#
# a = 1
#
# case false
# when a == 1
# puts "a is not 1"
# when a == 2
# puts "a is not 2"
# end
#
# I imagine that would get some readability complaints... But I
# kind of like it because once you get "false" in your head it's easier
# to follow, possibly, than a lot of unless/! stuff.
lol.
you are weird Not only do i get cross-eyed, i get my left-brain twisted w right. Though shall not combine targets with conditions