You may have noticed that some methods give you something back when you call them. For example, we say gets returns a string (the string you typed in), and the + method in 5+3 (which is really 5.+(3)) returns 8. The arithmetic methods for numbers return numbers, and the arithmetic methods for strings return strings.
It’s important to understand the difference between a method returning a value (returning it to the code that called the method), and your program outputting information to your screen, like puts does. Notice that 5+3 returns 8; it does not output 8 (that is, display 8 on your screen).
So, what does puts return? We never cared before, but let’s look at it now:
return_val = puts 'This puts returned:' |
puts return_val |
This puts returned: |
|
The first puts didn’t seem to return anything, and in a way it didn’t; it returned nil. Though we didn’t test it, the second puts did, too; puts always returns nil. Every method has to return something, even if it’s just nil.
Take a quick break, and write a program to find out what say_moo returns.
Are you surprised? Well, here’s how it works: the value returned from a method is simply the last expression evaluated in the method (usually just the last line of the method). In the case of say_moo, this means it returns puts 'mooooooo...'*number_of_moos, which is just nil since puts always returns nil. If we wanted all our methods to return the string 'yellow submarine', we would just need to put that at the end of them:
def say_moo number_of_moos |
puts 'mooooooo...'*number_of_moos |
'yellow submarine' |
end |
|
x = say_moo 3 |
puts x.capitalize + ', dude...' |
puts x + '.' |
mooooooo...mooooooo...mooooooo... |
Yellow submarine, dude... |
yellow submarine. |
(I have no idea why you’d want say_moo to work that way, but there you have it.)
Notice I said “the last expression evaluated” instead of simply “the last line” or even “the last expression”; it’s possible for the last line to be only a small part of an expression (like the end in an if expression), and it’s possible for the last expression not to be evaluated at all if the method has an explicit return:
def favorite_food name |
if name == 'Lister' |
return 'vindaloo' |
end |
|
if name == 'Rimmer' |
return 'mashed potatoes' |
end |
|
'hard to say...maybe fried plantain?' |
end |
|
def favorite_drink name |
if name == 'Jean-Luc' |
'tea, Earl Grey, hot' |
elsif name == 'Kathryn' |
'coffee, black' |
else |
'perhaps...horchata?' |
end |
end |
|
puts favorite_food('Rimmer') |
puts favorite_food('Lister') |
puts favorite_food('Cher') |
puts favorite_drink('Kathryn') |
puts favorite_drink('Oprah') |
puts favorite_drink('Jean-Luc') |
mashed potatoes |
vindaloo |
hard to say...maybe fried plantain? |
coffee, black |
perhaps...horchata? |
tea, Earl Grey, hot |
Make sure you follow each of the six delicious examples.
I did two different things in that program: with favorite_food I used explicit returns, and in favorite_drink I didn’t. Depending on the feel of the code, I’ll write a method one way or the other. If I’m trying to prune off special cases, I might use returns and leave the general case on the last line. If I think the options are all of relatively equal importance, I might use elsif and else like that…feels more egalitarian, you know?
OK, now that we can write our own methods, let’s try that psychology experiment program again. This time we’ll write a method to ask the questions for us. It will need to take the question as a parameter and return true if the person answers yes and false if they answer no. (Even though most of the time we just ignore the answer, it’s still a good idea for our method to return the answer. This way we can use it for the bed-wetting question, too.) I’m also going to shorten the greeting and the debriefing, just so this is easier to read:
def ask question |
while true |
puts question |
reply = gets.chomp.downcase |
|
if (reply == 'yes' || reply == 'no') |
if reply == 'yes' |
answer = true |
else |
answer = false |
end |
break |
else |
puts 'Please answer "yes" or "no".' |
end |
end |
|
answer # This is what we return (true or false). |
end |
|
puts 'Hello, and thank you for...' |
puts |
|
ask 'Do you like eating tacos?' # Ignore this return value |
ask 'Do you like eating burritos?' # And this one |
wets_bed = ask 'Do you wet the bed?' # Save this return value |
ask 'Do you like eating chimichangas?' |
ask 'Do you like eating sopapillas?' |
puts 'Just a few more questions...' |
ask 'Do you like drinking horchata?' |
ask 'Do you like eating flautas?' |
|
puts |
puts 'DEBRIEFING:' |
puts 'Thank you for...' |
puts |
puts wets_bed |
<= | Hello, and thank you for... |
| |
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 |
<= | Do you like eating sopapillas? |
=> | yes |
<= | Just a few more questions... |
Do you like drinking horchata? | |
=> | yes |
<= | Do you like eating flautas? |
=> | yes |
<= |
|
DEBRIEFING: | |
Thank you for... | |
| |
false |
Not bad, huh? We were able to add more questions (and adding questions is easy now), but our program is still quite a bit shorter. Nice…a lazy programmer’s dream.
3.17.78.150