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
check_age
gets
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.
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
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,
if b === a
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?
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.
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”.
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.
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
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?
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
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 …
when …
end
end
def case_B
case
when …
when …
end
end
case
when condition_A then case_A
when condition_B then case_B
end
Regards, Morton
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.