Thursday, November 10, 2011

Exercise 13: Parameters, Unpacking, Variables: Learn Ruby the Hard Way: Practicum

So far we have been including everything either in the script, getting information from the keyboard as an internal prompt (gets), or pulling in functionality from another file (require). These work well for basic interaction and are OK if we want to just call a script name and run it. It doesn't give us much flexibility, though, as to how much information we can provide up front (actually, it gives us no flexibility).

Most command line programs we run have the ability to be "fed" other input items right along with the name of the script or command (think of "grep text example" to pull out the word 'text' from the file 'example'). grep is a command. text and example are arguments to that command. This next example shows how to feed arguments to a Ruby script.

first, second, third = ARGV

puts "The script is called: #{$0}"
puts "Your first variable is: #{first}"
puts "Your second variable is: #{second}"
puts "Your third variable is: #{third}"

Before we get started, some cool stuff is happening here. ARGV is a special kind of variable (a CONSTANT, meaning we don't want to tweak it once we assign something to it. CONSTANT's are easy to spot. They are in ALL CAPS). ARGV means "argument variable". as it's name suggest, and values entered in on the command line will be stored in this value.

What we see happening in the first line is that ARGV will hold whatever we type in at the command line. It doesn't care how many items we provide (items being anything we type with a space between them, see my examples in the command prompt window below). In the first line, we also define three variables that will get the first three values that are typed in after the name of the script (if we type in no values, then the variables will be assigned NULL). Also, anything I type above and beyond the three defined variables don't get assigned anywhere but ARGV. This idea of taking variables and assigning them directly from the command line and from ARGV is what Zed calls "unpacking". I think it's a useful metaphor, it makes sense, and it shows that ARGV also still has all of the variable values it received.

The name of the script also has a variable value. It's called '$0'

[so here's my version]

[and here's its output]

What You Should See

Run the program like this:

ruby ex13.rb first 2nd 3rd
This is what you should see when you do a few different runs with different arguments:

$ ruby ex13.rb first 2nd 3rd
The script is called: ex13.rb
Your first variable is: first
Your second variable is: 2nd
Your third variable is: 3rd

$ ruby ex13.rb cheese apples bread
The script is called: ex13.rb
Your first variable is: cheese
Your second variable is: apples
Your third variable is: bread

$ ruby ex13.rb Zed A. Shaw
The script is called: ex13.rb
Your first variable is: Zed
Your second variable is: A.
Your third variable is: Shaw

Extra Credit

Try giving fewer than three arguments to your script. What values are used for the missing arguments?

[As demonstrated in my initial run, if you don't provide arguments, null avalues are assigned and the variables will print out as blank. If you assign two values, the first two will appear, the third will be blank. If you assign five values, the first three will appear and the fourth and fifth values will be ignored (they haven't been unpacked, they still in the ARGV warehouse]

Write a script that has fewer arguments and one that has more. Make sure you give the unpacked variables good names.

[see below]

Combine gets.chomp() with ARGV to make a script that gets more input from a user.

[so here was my first attempt]

[and here's what I got]

Hey wait a sec... why is it doing that?! Hmmm... I'm guessing we can't use a regular gets in this case because of the arguments on the command line. So I'm going to do something shameful... I'm going to peak ahead... and hey, this looks like it might work.

[second attempt]

[second output]

OK, that looks doable (yeah, we'll be getting into what that STDIN means tomorrow :) ).


By using the ARGV constant, and having the ability to unpack values into other variables, we can provide a lot of flexibility to our programs. This flexibility can help us pull values from many places (from the command line and from the user input to a program). Pulling from the command line allows us to set up things like "flags" and make other conditional options... but I'm getting ahead of myself. Suffice it to say, you are no longer limited to just your script for input.

No comments: