Tuesday, November 15, 2011

Exercise 18: Names, Variables, Code, Functions: Learn Ruby The Hard Way: Practicum

Big title, big topic. In most actual implementations of software, there's only so much code that you will be able to use from the base library or the built in functionality. Most, if not all, programming languages are designed to be extensible. What that means is that, if you want to represent things in simpler ways, you move functionality from your main script over to other files or libraries so that they can be references and so that they can be called.

These are called lots of different things in different languages (Procedures, methods, calls, etc.) but I personally like and think the word "function" works the best, and heh, it seems Zed and Rob do, too :).

Functions do three things:

1. They name pieces of code the way variables name strings and numbers.

2. They take arguments the way your scripts take ARGV.

3. Using #1 and #2 they let you make your own "mini scripts" or "tiny commands".

Functions are defined in Ruby by using the word "def" (which stands for define, conveniently enough :) ). Our exercise today has to do with four functions we will create and then call in turn.

So those are four ways of handling functions, and each does it just a little bit differently.

The first function, puts_two, is structured a lot like how we handle a script that takes parameters from the command line (remember ARGV?). In Ruby function calls, though, we can't use ARGV (why? because it's already used by our main script). Thus, if we want to define any input that comes in as parameters to our function, we can say "*args" and it means thew same thing; any input into the function will be parsed as a separate parameter. The name of the function doesn't matter, as long as it is meaningful enough to us to remember it or be able to call it easily (me personally, I am all about descriptive function names, as close to their actual use as possible. Self commenting code and all that).Once we define the function, give it a name, and declare how it handles arguments, we then structure the code inside the function to do what we want to have it do. In this case, we unpack the *args, put them into two variables (or how many we want to declare), and then print them out. The word "end", as it implies, ends our function.

Now, unlike the command line where we would potentially be giving variable amounts of data and dealing with it, in our scripts themselves, it's unlikely that we will have a need for wildly varying argument values. In fact, it's much more likely we will have exactly the parameters we want to work with. With Ruby functions (and many other languages) the whole unpacking step can be skipped. By defining the args during the definition and putting them inside the (). print_two_again does exactly this.

puts_one is an example of a function that takes a single argument, while puts_none shows what happens when you call a function directly, i.e. without any arguments to pass to it.

What You Should See

If you run the above script you should see:

$ ruby ex18.rb
arg1: 'Zed', arg2: 'Shaw'
arg1: 'Zed', arg2: 'Shaw'
arg1: 'First!'
I got nothin'.

So does some of this look familiar? It should, most of the commands we have been running in our scripts, especially any that have parentheses () are functions. We just didn't realize it. This means you have the ability to make your own commands, and call them what you want to call them. If you'd like to make equations that you can solve, you can feed the parameters into a function, and then have the operations performed and an answer returned to you (in fact, that's exactly how mathematical functions work, too).

Extra Credit

Write out a function checklist for later exercises. Write these on an index card and keep it by you while you complete the rest of these exercises or until you feel you do not need it:

Index Card #1: Defining and Creating "Functions" in Ruby

- Did you start your function definition with def?
- Does your function name have only characters and _ (underscore) characters?
- Did you put an open parenthesis ( right after the function name?
- Did you put your arguments after the parenthesis ( separated by commas?
- Did you make each argument unique (meaning no duplicated names).
- Did you put a close parenthesis ) after the arguments?
- Did you indent all lines of code you want in the function 2 spaces?
- Did you close your function body by typing "end"?

- And when you run (aka "use" or "call") a function, check these things:

Index Card #2: Calling and Running "Functions" in Ruby

- Did you call/use/run this function by typing its name?
- Did you put ( character after the name to run it? (this isn't required, but is idiomatic)
- Did you put the values you want into the parenthesis separated by commas?
- Did you end the function call with a ) character.
- Use these two checklists on the remaining lessons until you do not need them anymore.

Repeat this a few times:

"To 'run', 'call', or 'use' a function all mean the same thing."

And one more thing... it's a good bet that most of the people that program in Ruby will not call these functions. They will call them "methods". What you ultimately call them will depend a lot on who you work with. Just note that when someone you work with refers to a "method" or a "function", most of the time they are talking about the same thing.

No comments: