Friday, November 18, 2011

Exercise 21: Functions Can Return Something: Learn Ruby The Hard Way: Practicum

Remember a couple of days ago I talked about the idea of a function being like a guitar pedal where the cord from the guitar (and the signal from the pickups) goes into the pedal, some magic and processing happens, and the sound that comes out the other end goes to your amp? Well, many guitarists use multiple pedals, and through these multiple pedals, the output of one pedal is the input of another, with its own processing, and it sends it down the line until it gets to the amp. this is called "signal flow" and at different times, one pedal, or two pedals, or sometimes five or six, will be active at the same time.
This is a good analogy (I think) for passing values from one function to another, and the way to do that is through the functions "return value". If you have ever programmed in C or Pascal or other procedural languages, you may already be familiar with the return value of a function. Generally, the last value, the final result, the end product is often the return value, but not always. In C, if everything happens correctly, we often return a value of "0" as an "all's well" or a value of "-1" if there's an error. What does Ruby do? Let's find out.

In Ruby, the last evaluated statement in a method is its return value. You can also be more explicit if you want and type "return a + b", but it's not necessary.

What You Should See

$ ruby ex21.rb
Let's do some math with just functions!
ADDING 30 + 5
DIVIDING 100 / 2
Age: 35, Height: 74, Weight: 180, IQ: 50
Here is a puzzle.
ADDING 35 + -4426
That becomes:  -4391 Can you do it by hand?

Extra Credit

If you aren't really sure what return values are, try writing a few of your own functions and have them return some values. You can return anything that you can put to the right of an =.

[The key to notice is that, as was stated earlier, if we want to be explicit, we can say in the final line "return a+b" or any other value we want to reflect. It's what the last statement evaluates to that is returned, and it can be used as a value to feed another function if we want to].

At the end of the script is a puzzle. I'm taking the return value of one function, and using it as the argument of another function. I'm doing this in a chain so that I'm kind of creating a formula using the functions. It looks really weird, but if you run the script you can see the results. What you should do is try to figure out the normal formula that would recreate this same set of operations.

[Well, it's up in the What You Should See section. If we take (50/2), which is 25, then feed 180 * 25, then feed -4500 from 74 (or 74 -4500) gives us -4426 and then adds 35 to it, giving us -4391 as the final answer].

Once you have the formula worked out for the puzzle, get in there and see what happens when you modify the parts of the functions. Try to change it on purpose to make another value.

Finally, do the inverse. Write out a simple formula and use the functions in the same way to calculate it.


So the cool thing here is any change in any of the values will modify that end result, because each function call passes a return value to the next one in the chain. This might seem contrived, but the truth is, this is a very common practice, taking a value from one function and passing it to another, and then passing that resulting value to another function, and so on and so on. Think of using the pipe command in UNIX. You run a command and get a certain output, you then pipe that output to another command, and it does something,and you then pipe that output to yet another command:

$ grep "value" textfile.txt | sort | uniq

Look somewhat familiar? in may ways, that's exactly the same thing as passing return values from functions into other functions. Again, signal flow for the win :).

No comments: