As we’ve seen, loops and iterators allow us to do the same thing (run the same code) over and over again. However, sometimes we want to do the same thing a number of times but from different places in the program. For example, let’s say we were writing a questionnaire program for a psychology student. From the psychology students I have known and the questionnaires they have given me, it would probably go something like this:
puts 'Hello, and thank you for taking the time to' |
puts 'help me with this experiment. My experiment' |
puts 'has to do with the way people feel about' |
puts 'Mexican food. Just think about Mexican food' |
puts 'and try to answer every question honestly,' |
puts 'with either a "yes" or a "no". My experiment' |
puts 'has nothing to do with bed-wetting.' |
puts |
# We ask these questions, but we ignore their answers. |
while true |
puts 'Do you like eating tacos?' |
answer = gets.chomp.downcase |
if (answer == 'yes' || answer == 'no') |
break |
else |
puts 'Please answer "yes" or "no".' |
end |
end |
|
while true |
puts 'Do you like eating burritos?' |
answer = gets.chomp.downcase |
if (answer == 'yes' || answer == 'no') |
break |
else |
puts 'Please answer "yes" or "no".' |
end |
end |
|
# We pay attention to *this* answer, though. |
while true |
puts 'Do you wet the bed?' |
answer = gets.chomp.downcase |
if (answer == 'yes' || answer == 'no') |
if answer == 'yes' |
wets_bed = true |
else |
wets_bed = false |
end |
break |
else |
puts 'Please answer "yes" or "no".' |
end |
end |
|
while true |
puts 'Do you like eating chimichangas?' |
answer = gets.chomp.downcase |
if (answer == 'yes' || answer == 'no') |
break |
else |
puts 'Please answer "yes" or "no".' |
end |
end |
|
puts 'Just a few more questions...' |
|
while true |
puts 'Do you like eating sopapillas?' |
answer = gets.chomp.downcase |
if (answer == 'yes' || answer == 'no') |
break |
else |
puts 'Please answer "yes" or "no".' |
end |
end |
|
# Ask lots of other questions about Mexican food. |
|
puts |
puts 'DEBRIEFING:' |
puts 'Thank you for taking the time to help with' |
puts 'this experiment. In fact, this experiment' |
puts 'has nothing to do with Mexican food. It is' |
puts 'an experiment about bed-wetting. The Mexican' |
puts 'food was just there to catch you off guard' |
puts 'in the hopes that you would answer more' |
puts 'honestly. Thanks again.' |
puts |
puts wets_bed |
<= | Hello, and thank you for taking the time to |
help me with this experiment. My experiment | |
has to do with the way people feel about | |
Mexican food. Just think about Mexican food | |
and try to answer every question honestly, | |
with either a "yes" or a "no". My experiment | |
has nothing to do with bed-wetting. | |
| |
Do you like eating tacos? | |
=> | yes |
<= | Do you like eating burritos? |
=> | yes |
<= | Do you wet the bed? |
=> | no way! |
<= | Please answer "yes" or "no". |
Do you wet the bed? | |
=> | NO |
<= | Do you like eating chimichangas? |
=> | yes |
<= | Just a few more questions... |
Do you like eating sopapillas? | |
=> | yes |
<= |
|
DEBRIEFING: | |
Thank you for taking the time to help with | |
this experiment. In fact, this experiment | |
has nothing to do with Mexican food. It is | |
an experiment about bed-wetting. The Mexican | |
food was just there to catch you off guard | |
in the hopes that you would answer more | |
honestly. Thanks again. | |
| |
false |
Psych majors…. Anyway, that was a pretty long program—a long, ugly program with lots of ugly repetition. All of the sections of code around the questions about Mexican food were identical except for the food, and the bed-wetting question was only slightly different.
As we’ve talked about before, repetition is a Bad Thing. Still, we can’t change the repeated code to a big loop or iterator, because sometimes we have things we want to do between questions. In situations like these, it’s best to write a method of your own. Let’s start with something small and return to the psych program later.
Let’s write a method that just says “moo”:
def say_moo |
puts 'mooooooo...' |
end |
|
Um…our program didn’t say_moo. Why not? Because we didn’t tell it to. We told it how to say_moo, but we never actually said to do it. Let’s give it another shot.
def say_moo |
puts 'mooooooo...' |
end |
|
say_moo |
say_moo |
puts 'coin-coin' |
say_moo |
say_moo |
mooooooo... |
mooooooo... |
coin-coin |
mooooooo... |
mooooooo... |
Ahhh, much better.
Just in case you don’t speak French, that was a French duck in the middle of the program. The ducks over there say “coin-coin,” I hear. Unfortunately, the only things I retained from Compulsory French 101 were that and a few words I’m not allowed to write (in case we ever decide to translate this book into Canadian).
So, we defined
the method say_moo. (Method names, like
variable names, almost always start with a lowercase letter.
There are a few exceptions, though, such as +
or ==.)
But don’t methods always have to be associated with
objects? Well, yes, they do, and in this case (as with
puts and gets),
the method is just associated with the object representing
the whole program. In Chapter 13, Creating New Classes,
Changing Existing Ones,
we’ll see how to add methods to other objects. But first…
18.220.111.6