Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Writing Your Own Methods
- # 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 the answers.
- goodAnswer = false
- while (not goodAnswer)
- puts 'Do you enjoy eating tacos?'
- answer = gets.chomp.downcase
- if (answer == 'yes' or answer == 'no')
- goodAnswer = true
- else
- puts 'Please answer "yes" or "no".'
- end
- end
- goodAnswer = false
- while (not goodAnswer)
- puts 'Do you lieke eating burritos?'
- answer = gets.chomp.downcase
- if (answer == 'yes' or answer == 'no')
- goodAnswer = true
- else
- puts 'Please answer "yes" or "no".'
- end
- end
- # We pay attention to the answer below, however.
- goodAnswer = false
- while (not goodAnswer)
- puts 'Do you wet the bed?'
- answer = gets.chomp.downcase
- if (answer == 'yes' or answer == 'no')
- goodAnswer = true
- if answer == 'yes'
- wetsBed = true
- else
- wetsBed = false
- end
- else
- puts 'Please answer "yes" or "no".'
- end
- end
- goodAnswer = false
- while (not goodAnswer)
- puts 'Do you like eating chimichangas?'
- answer = gets.chomp.downcase
- if (answer == 'yes' or answer == 'no')
- goodAnswer = true
- else
- puts 'Please answer "yes" or "no".'
- end
- end
- puts 'Just a few more questions...'
- goodAnswer = false
- while (not goodAnswer)
- puts 'Do you like eating sopapillas?'
- answer = gets.chomp.downcase
- if (answer == 'yes' or answer == 'no')
- goodAnswer = true
- 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 wetsBed
- # Repetition is a bad thing. Still, we can't make it into 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. You want to tell the program HOW to say mooo and to DO it.
- def sayMoo
- puts 'moooooo...'
- end
- sayMoo
- sayMoo
- puts 'coin-coin' # French Duck speaking...
- sayMoo
- sayMoo
- # So we defined the method sayMoo. (Method names, like variable names, start with a lowercase letter. There are a few exceptions, though, like + 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.
- # Method Parameters
- # some methods (like gets, to_s, reverse...) you can just call on an object. However, other methods (like +, -, puts...) take parameters to tell the object how to do the method. For example, you wouldn't just say 5+, right? You're telling 5 to add, but you aren't telling it what to add.
- # To add a parameter to sayMoo (let's say, the number of moos), we would do this:
- def sayMoo numberOfMoos
- puts 'moooooooo...'*numberOfMoos
- end
- sayMoo 3
- puts 'oink-oink'
- # sayMoo
- # Returns an error because the parameter is missing.
- # numberOfMoos is a variable which points to the parameter passed in. So if I type in sayMoo 3, then the parameter is 3, and the variable numberOfMoos points to 3. Thus, the parameter is REQUIRED. If objects in Ruby are like nouns in English, and methods are like verbs, then you can think of parameters as adverbs (like with sayMoo, where the parameter told us how to sayMoo) or sometimes as direct objects (like with puts, where the parameter is what gets putsed).
- # Local Variables
- def doubleThis num
- numTimes2 = num*2
- puts num.to_s+' doubled is '+numTimes2.to_s
- end
- doubleThis 44
- # The variables are num and numTimes2. They both sit inside the method doubleThis. These (and all of the variables you have seen so far) are local variables. This means that they live inside the method, and they cannot leave. If you try, you will get an error:
- # def doubleThis num
- # numTimes2 = num*2
- # puts num.to_s+' doubled is '+numTimes2.to_s
- # end
- # doubleThis 44
- # puts numTimes2.to_s
- # Error Message - Undefined local variable... In fact, we did define that local variable, but it isn't local to where we tried to use it; it's local to the method.
- # While it does mean that you have no access to variables inside methods, it also means that they have no access to your variables, and thus can't screw them up:
- def littlePest var
- var = nil
- puts 'HAHA! I ruined your variable!'
- end
- var = 'You can\'t even touch my variable!'
- littlePest var
- puts var
- # There are actually two variables in that little program named var: one inside littlePest, and one outside of it. When we called littlePest var, we really just passed the string from one var to the other, so that both were pointing to the same string. Then littlePest pointed its own local var to nil, but that did nothing to the var outside the method.
- # Return Values
- # Arithmetic methods for numbers return numbers, and arithmetic methods for strings return strings.
- # Important to understand the difference between methods returning a value to where the method was called, and your program outputting information to your screen, like puts does. Notice that 5+3 returns 8; it does not output 8.
- # So what does puts return? We never cared before, but let's look at it now:
- returnVal = puts 'This puts returned:'
- puts returnVal # So the first puts 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.
- # Write a program to find out what sayMoo returned.
- # Here's how it works: the value returned from a method is simply the last line of the method. In the case of sayMoo, this means it returns puts 'mooooooo...'*numberOfMoos, which is just nil since puts always returns nil. If we wanted all of our methods to return the string 'yellow submarine', we would just need to put that at the end of them:
- def sayMoo numberOfMoos
- puts 'moooooo...'*numberOfMoos
- 'yellow submarine'
- end
- x = sayMoo 2
- puts x
- # Let's try that psychology experiment again, but 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 they answered yes and false if they answered 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
- goodAnswer = false
- while (not goodAnswer)
- puts question
- reply = gets.chomp.downcase
- if (reply == 'yes' or reply =='no')
- goodAnswer = true
- if reply == 'yes'
- answer = true
- else
- answer = false
- end
- 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?' # We ignore this return value.
- ask 'Do you like eating burritos?'
- wetsBed = ask 'Do you wet the bed?' # We save this return value.
- ask 'Do you like eating chimichangas?'
- ask 'Do you like eating sopapillas?'
- ask 'Do you like eating tamales?'
- puts 'Just a few more questions...'
- ask 'Do you like drinking horchata?'
- ask 'Do you like eating flautas?'
- puts
- puts 'BEBRIEFING:'
- puts 'Thank you for...'
- puts
- puts wetsBed
- # englishNumber Example Method
- # This program will take a number, like 22, and return the englishversion of it (in this case, the string 'twenty-two'). For now let's have it only work on intefers from 0 to 100.
- # (NOTE: This method uses a new trick to return from a method early using the return keyword, and introduces a new twist on branching: elsif. It should be clear in context how these work.)
- def englishNumber number
- # We only want numbers from 0-100
- if number < 0
- return 'Please enter a number zero or greater.'
- end
- if number > 100
- return 'Please enter a number 100 or lesser.'
- end
- numString = '' # This is the string we will return.
- # "left" is how much o the number we still have left to write out.
- # "write" is the part we are writing out right now.
- # write and left... get it? ;)
- left = number
- write = left/100 # How many hundreds left to write out?
- left = left - write*100 # Subtract off those hundreds.
- if write > 0
- return 'one hundred'
- end
- write = left/10 # How many tens left to write out?
- left = left - write*10 # Subtract off those tens.
- if write > 0
- if write == 1 # Uh-oh...
- # Since we can't write "twenty-two" instead of "tweleve",
- # we have to make a special exception for these
- if left == 0
- numString = numString + 'ten'
- elsif left == 1
- numString = numString + 'eleven'
- elsif left == 2
- numString = numString + 'twelve'
- elsif left == 3
- numString = numString + 'thirteen'
- elsif left == 4
- numString = numString + 'fourteen'
- elsif left == 5
- numString = numString + 'fifteen'
- elsif left == 6
- numString = numString + 'sixteen'
- elsif left == 7
- numString = numString + 'seventeen'
- elsif left == 8
- numString = numString + 'eighteen'
- elsif left == 9
- numString = numString + 'nineteen'
- end
- # Since we took care of the digit in the ones place already,
- # we have nothing left to write.
- left = 0
- elsif write == 2
- numString = numString + 'twenty'
- elsif write == 3
- numString = numString + 'thirty'
- elsif write == 4
- numString = numString + 'forty'
- elsif write == 5
- numString = numString + 'fifty'
- elsif write == 6
- numString = numString + 'sixty'
- elsif write == 7
- numString = numString + 'seventy'
- elsif write == 8
- numString = numString + 'eighty'
- elsif write == 9
- numString = numString + 'ninety'
- end
- if left > 0
- numString = numString + '-'
- end
- end
- write = left # How many ones left to write out?
- left = 0 # Subtract off those ones.
- if write > 0
- if write == 1
- numString = numString + 'one'
- elsif write == 2
- numString = numString + 'two'
- elsif write == 3
- numString = numString + 'three'
- elsif write == 4
- numString = numString + 'four'
- elsif write == 5
- numString = numString + 'five'
- elsif write == 6
- numString = numString + 'six'
- elsif write == 7
- numString = numString + 'seven'
- elsif write == 8
- numString = numString + 'eight'
- elsif write == 9
- numString = numString + 'nine'
- end
- end
- if numString == ''
- # The only way "numString" could be empty is if "number" is 0
- return 'zero'
- end
- # If we got this far, then we had a number somewhere in between
- # 0 and 100, so we need to return "numString".
- numString
- end
- puts englishNumber( 0)
- puts englishNumber( 9)
- puts englishNumber( 10)
- puts englishNumber( 11)
- puts englishNumber( 17)
- puts englishNumber( 32)
- puts englishNumber( 88)
- puts englishNumber( 99)
- puts englishNumber(100)
- # PROBLEMS: First, it has too much repetition. Second, it doesn't handle numbers greater than 100. Third, there are too many special cases, too many returns. Let's use some arrays and try to clean it up a bit:
- def englishNumber number
- if number < 0 # No negative numbers.
- return 'Please enter a number that isn\'t negative.'
- end
- if number == 0
- return 'zero'
- end
- # No more special cases! no more returns!
- numString = '' # This is the string we will return.
- onesPlace = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
- tensPlace = ['ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
- teenagers = ['eleven', 'tweleve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
- # "left" is how much of the number we still have left to write out.
- # "write" is the part we are writing out wright now.
- # write and left.. get it? ;)
- left = number
- write = left/100 # How many hundreds left to write out?
- left = left - write*100 # Subtract off those hundreds.
- if write > 0
- # Now here's a really sly trick:
- hundreds = englishNumber write
- numString = numString + hundreds + ' hundred'
- # That's called "recursion". So what did I just do?
- # I told this method to call itself, but with "write" instead of
- # "number". Remember that "write" is (at the moment) the number of
- # hundreds we have to write out. After we add "hundreds" to "numString"
- # we add the string ' hundred' after it. So, for example, if
- # we originally called englishNumber with 1999 (so "number" = 1999),
- # then at this point "write" would be 19, and "left" would be 99.
- # The laziest thing to do at this point is to have englishNumber
- # write out the 'nineteen' for us, then we write out ' hundred',
- # and then the rest of englishNumber writes out 'ninety-nine'.
- if left > 0
- # So we don't write 'two hundredfifty-one'...
- numString = numString + ' '
- end
- end
- write = left/10 # How many tens left to write out?
- left = left - write*10 # Subtract off those tens.
- if write > 0
- if ((write == 1) and (left > 0))
- # Since we can't write "twenty-two" instead of "twelve",
- # we have to make a speecial exception for these.
- numString = numString + teenagers[left-1]
- # The "-1" is because teenagers[3] is 'fourteen', not 'thirteen'.
- # Since we took care of the digit in the ones place already,
- # we have nothing left to write.
- left = 0
- else
- numString = numString + tensPlace[write-1]
- # The "-1" is because tensPlace[3] s 'forty', not 'thirty'.
- end
- if left > 0
- # So we don't write sixtyfour'...
- numString = numString + '-'
- end
- end
- write = left # How many ones left to write out?
- left = 0 # Subtract off those ones.
- if write > 0
- numString = numString + onesPlace[write-1]
- # The "-1" is because onesPlace[3] is 'four', not 'three'.
- end
- # Now we just return "numString"...
- numString
- end
- puts englishNumber( 0)
- puts englishNumber( 9)
- puts englishNumber( 10)
- puts englishNumber( 11)
- puts englishNumber( 17)
- puts englishNumber( 32)
- puts englishNumber( 88)
- puts englishNumber( 99)
- puts englishNumber(100)
- puts englishNumber(101)
- puts englishNumber(234)
- puts englishNumber(3211)
- puts englishNumber(999999)
- puts englishNumber(1000000000000)
Add Comment
Please, Sign In to add comment