Chapter 3. Variables
WHAT YOU WILL LEARN IN THIS CHAPTER:
Understanding scalars, arrays, and hashes
Accessing values of scalars, arrays, and hashes, and printing them out
Understanding Perl’s “special” variables
Using Perl’s context feature
Understanding the scope of variables
This chapter examines the three primary data types of Perl: scalars, arrays, and hashes. Unlike many other languages that focus on things like “strings,” “integers,” “floats,”, and so on, Perl’s types focus on how you organize your data, rather than what the data is. It’s an approach to data types that is unusual to those who think of “types” as restricting data to certain values, but in practice, it’s a robust, powerful approach that many other programming languages follow.
Don’t worry about the size of this chapter because you won’t need to memorize it. Most of this information will be reinforced in subsequent chapters. Primarily, you’ll want to understand how to create and assign values to Perl’s three primary data types (scalars, arrays, and hashes). You’ll also want to ensure that you understand context, because it will come up repeatedly in your career as a Perl programmer. Many inexperienced Perl programmers struggle to understand bugs in context, because it’s often treated as an afterthought.
What Is Programming?
’You’ve already received quite a bit of background about Perl, but now is the time to start programming. For those new to programming, a Perl program is a file—often many files—of text instructions telling the computer what to do with some data. For example, pretend that the following is a program to send cucumber recipes to a cucumber fetish mailing list. This program uses what is called “pseudocode,” a made-up language designed to explain programming ideas.
email_addresses = read_list_of_email_addresses() cuke_recipe = read_new_recipe() for each address in email_addresses email_to(address, cuke_recipe)
Even if you have never programmed before, you can probably guess what each line in this “program” does. At its core, there’s really nothing mysterious about programming. Take some data and do something with it.
But where is this data? Usually, when you have data in a program, you keep it in something called a variable, and variables are the little beasties everyone loves and hates. They’re the things you always get wrong, but have to get oh so right. As you program, many of your errors will be the wrong data in the wrong variable. Have fun!
A Few Things to Note Before Getting Started
The following sections discuss a few general concepts that will make this chapter much easier to follow.
strict, warnings, and diagnostics
You’ll learn more detail about this later, but for now, assume that every code snippet begins like this:
use strict; use warnings; use diagnostics;
Those three statements will save you a lot of pain. They force you to properly declare most variables and subroutines, warn you when you’re doing silly things, and, if you include the use diagnostics line, actually give you an extended description of what you did wrong, along with suggestions on how to fix it. Experienced programmers generally omit diagnostics, but when you’re starting out, they’re invaluable.
Note
These three lines won’t be listed those for every code snippet because it would just be useless noise. When you don’t see them, assume they’re there unless you are told otherwise, though they will be slipped in from time to time as a reminder.
Next, let’s look at a few variables.
my $nick_name = 'Ovid'; my @cats = ( 'Valentin', 'Arthur' ); my $nick = $nick_name; print $nick;
That example assigns values to some variables. The statement in the third line copies the string ‘Ovid’ from the variable $nick_name to the variable $nick. The print statement will print the word Ovid to your console.
If you’re an experienced programmer, you already understand much of what’s going on here, and you can probably guess a lot more. But let’s now cover some common ground that will apply to most variables you work with in Perl.
The my Function
Notice how each variable in the preceding code example is declared with the my function. This function in Perl is the most common way of declaring a variable, and it also makes the variable visible only to the current scope (which is covered later in this chapter) to hide it from other parts of your program. That’s important to ensure that a distant part of your program doesn’t silently change your data.
Note
For more information, see perldoc -f my. (The -f switch is used to list functions.)
Note that there are other ways to declare variables and, in fact, the variable declaration is sometimes optional. You’ll learn more about that later, but for now, be sure to declare your variables with my, as shown here:
my $nick_name = 'Ovid';
This will protect this part of your program from being accidently changed by another part where you used the same variable name. That kind of self-inflicted bug is all too easy to create, and extremely difficult to find and fix. Use my and you’ll make your programming life easier.
Note
Even experienced Perl programmers will object to describing my as a function. However, Perl’s distinction between functions, operators, and keywords is a bit fuzzy at times, it’s understandable that this is a point of disagreement for some people. The key takeaway here is simple: Don’t get hung up on terminology.
Sigils
Moving a bit further to the right in the sample code presented at the beginning of this discussion, you see punctuation before each variable name—in this case the dollar sign, $, as shown here:
my $nick_name = 'Ovid';
In Perl, this leading punctuation is called a sigil because, like the word “scalar.” it is a common word that has been “repurposed.” A sigil was originally a carved or painted symbol of great power. So, in Perl, a sigil is a punctuation symbol that tells you something about the variable you’re using.
Getting back to that dollar sign sigil, in Perl, when you see a variable beginning with a dollar sign, you know that you’re accessing a $calar value. The “S” shape of the dollar sign is a (theoretically) handy mnemonic for scalar. Or maybe it’s a handy mnemonic for $ingle value.
Note the phrase, “you’re accessing a $calar value.” That does not read, “contains a scalar value.” When you learn about arrays and hashes (or containers that can contain multiple values), the leading “$” will show you when you’re accessing a $ingle value of the array or hash, instead of multiple values. You’ll learn more that when you discover arrays and hashes.
Note
For more information, see perldoc perldata.
Identifiers
Variables usually have names. In fact, many things in Perl have names, also called “identifiers.” These are things like subroutines (discussed in Chapter 7, Subroutines), filehandles (discussed in Chapter 9, Files and Directories), packages (discussed in Chapter 11, Packages and Modules), and a few others. In fact, just about anything you can pick a name for in Perl follows fairly simple naming rules.
Note
For more information, see perldoc perlglossary
Perl names must start with a leading (ASCII) letter or underscore. You can optionally follow that with one or more letters, numbers or underscores. The following are all valid variable names:
my $x; my $foo; my $_some_1; my $DontMakeVariableNamesLikeThis; my $make_names_like_this_instead; my $item_3; my $verily_I_say_unto_you_the_number_of_the_tr_tag_shall_be;
(The author used that last one in anger in a project several years ago, and somewhere out there is a maintenance programmer who wants to kill him.)
As a matter of style in Perl (yes, Perl has a style, as you can see at perldoc perlstyle), you don’t use camelCaseWords. Instead, we use words_separated_by_underscores. This is because the latter is easier to read, particularly for those who do not speak English as a first language. The practice of camelCase is merely a holdover from older programming languages that didn’t allow underscores in identifiers. Perl programmers are not really down with arbitrary limitations imposed by archaic programming conventions. They have enough arbitrary limitations already, thank you.
The following are not valid variable names:
my $answer-to-life; my $~destructor; my $3rd_times_the_charm;
As with all things in life and Perl, there are some caveats, the biggest of which is that Perl is allowed to violate the rules it sets for you. So, in Perl programs, you’ll sometimes see things the following:
my $host = $1;
my $this_perl = $^X;
my $taint_mode = ${^TAINT};You can read about these and other special variables in perldoc perlvar. We’ll cover the most common ones in the book as they come up.
Note
Note that all the previous names use ASCII characters. Though it is generally not recommended, you can use UTF8 characters in your identifiers by using the use utf8 pragma, as shown here:
use utf8; my $cédille = 'French letter'; print $cédille;
Even though you can do this, you shouldn’t, given that many programmers cannot type these characters.
Scalars
In Perl, a scalar is merely a single value. Following are some scalars:
my $celsius_temp = 37; my $nick_name = 'Ovid';
A scalar can be a number, a string, or a reference (you’ll learn more about references in Chapter 6, References—hold your horses). If you have a math or physics background, forget that you might know another definition for scalar. In Perl, it just means a single value.
Note
For more information, see perldoc intro.
In the previous example, my is a function declaring the variable, followed by the variable itself, followed by the assignment operator (=), following by a numeric literal (37), or a string literal, (‘Ovid’).
Note
A literal is a hard-coded value in a program, as opposed to a variable containing that value. See perldoc perlglossary for this and other terms you may be unfamiliar with.
If you don’t assign anything to the variable, it has a special value called undef.
my $var; # its value is undef
As you progress through this book, you’ll see that a variable with an undef value will often cause “uninitialized” warnings in your code. We’ll see some of those warnings later and give you tips on how to avoid them.
If you prefer, you can declare several scalars at once by putting parentheses around them, as shown here:
my ( $celsius_temp, $nick_name );
And you can even assign to them when you declare them by putting parentheses around the right-hand side, as shown here:
my ( $celsius_temp, $nick_name ) = ( 37, 'Ovid' );
As you might expect, that assigns 37 to $celsius_temp and “Ovid” to $nick_name.
Strings
Assigning a string to a scalar is simple:
my $person = 'Leila'; my $wife = "lovely";
Both of these lines of code are valid ways of assigning a string to a scalar. When using single quotes, what you see inside of the quotes is generally exactly what you get. However, when you use double quotes, you can use escape characters (“\n” for newline, “\t” for tab, and so on) and interpolate (embed) other variables in the string. Following is example that will print out “lovely Leila” with a newline at the end:
my $person = 'Leila'; my $wife = "lovely $person"; print "$wife\n";
Sometimes you need to include quotes in your quotes. You can escape the quotes or use a different set of quotes, as shown here:
my $city = 'R\'lyeh'; my $city = "R'lyeh"; print $city;
Quotes and Quote Operators
Sometimes, though, you must interpolate something and use double quotes at the same time, as shown here:
my $reviewer = 'Adrian'; my $review = "$reviewer wrote \"This book is awful\"";
That can be painful and confusing to read, so Perl provides rich “quotelike” operators (see perldoc perlop and search for “Quote-like Operators”). The q{} replaces single quotes and qq{} replaces double-quotes. This can eliminate much painful escaping.
my $reviewer = 'Adrian';
my $review = qq{$reviewer wrote "This book is wonderful"};Also, the actual delimiter used with q and qq does not need to be curly braces ({}). It could be almost any pair of delimiters you choose, such as shown in the following examples:
my $review = qq!$reviewer wrote "This book is awful"!; my $review = qq<$reviewer wrote "This book is awful">; my $review = qq[$reviewer wrote "This book is awful"]; my $review = qq($reviewer wrote "This book is awful"); my $review = qq@$reviewer wrote "This book is awful"@;
You can even use quotes over multiple lines, as shown here:
my $letter = qq{
Dear $editor,
I really liked the subtitle which you rejected and beg you to reconsider.
It was brilliant and perfectly conveyed the tone of this book. In case
you wish to reconsider, it's:
"Get a job, hippy!"
Sincerely,
Ovid
};However, if you go that route, it’s generally considered better to use “here-docs.” These types of strings require a << followed by a string literal of your choosing. All following text will be included in the string until the string literal is found again:
my $letter = <<"END_APOLOGY"; Dear $editor, I'm very sorry for mocking you in the last email. I promise it won't happen again. Can I still get paid? Sincerely, Ovid END_APOLOGY
Just about any string literal can be used.
my $get_customers_with_orders = <<'SQL;; SELECT c.id FROM customers c JOIN orders o ON c.id = o.customer_id SQL
Just be sure to pick a descriptive literal (END is a popular one) for the here-doc. Yes, you can use a single dot (.) or even an empty string, but this is considered bad style, and can lead to confusing code, or even strange errors.
Warning
The final string literal in a here-doc must have a newline at the end of it, or Perl won’t see it, and you’ll get an error like this:
Can't find string terminator "END_APOLOGY" anywhere before EOF.
It’s a confusing thing that trips up a few people.
Note
You can also use here-docs with single quotes, in which case nothing inside of the here-doc will be interpolated.
Escape Sequences
Many times when creating strings you’ll come across characters that can be awkward to type. The full list can be seen with perldoc perlop, but Table 3.1, “Main Escape Sequences” shows the main escape sequences you’ll encounter.
Table 3.1. Main Escape Sequences
Sequence | Description |
|---|---|
| Tab |
| Newline |
| Carriage return |
| Wide hex character |
| Named Unicode character |
Now, consider the following:
print "I mean it!\nI'm really sorry for mocking you!";
This line of code prints the following:
I mean it! I'm really sorry for mocking you!
Table 3.2, “Special Escape Sequences” shows a few special escape sequences that are less common, but are sometimes used to control the “case” of characters.
Table 3.2. Special Escape Sequences
Sequence | Description |
|---|---|
| Lower case next character |
| Upper case next character |
| Lower case until \E |
| Upper case until \E |
| End case modification |
You can use these just as you would other escape characters. For example, the following will print “E.E. Cummings” and offend your literature professor:
print "\Ue.e. c\Eummings\n";
Numbers
Integers and floats
Scalars can hold numbers, too. Just assign the numbers to them:
my $answer = 42; my $body_temp_fahrenheit = 98.6;
Note that you can use integers or floats as needed. Internally, Perl will store these numbers however the C compiler which built Perl supports them.
Integers are represented exactly, but as with other programming languages, floating point numbers will only be an approximation because of how computers store numbers internally. For example, the int function takes the integer value of a number, but this can lead to unpleasant surprises:
print int(4.39 * 100);
Depending on your Perl, that will likely print 438 instead of 439. That’s because 4.39 is represented internally as something like 4.3899999999999 and when you multiply it by 100 and drop the decimal part, you get 438. Note that this is a general limitation with programming languages, not just Perl.
Octal, Hex, and Exponential Notation
If you need to, you can designate numbers as octal or hex by prepending them with a 0 or 0x respectively:
my $answer = 052; # 42 in decimal my $hex_number = 0xFF; # 255 in decimal my $hex_number = 0xff; # also 255 in decimal
You can also use exponential notation if needed and like many other languages, Perl is rather flexible about how you write it. The following are all equivalent:
my $number_of_stars_in_universe = 3e23; my $number_of_stars_in_universe = 3E+23; my $number_of_stars_in_universe = 3.0e+23;
Naturally, you can represent very small numbers with this, too.
my $electron_mass = 9.1093822e-31;
Perl doesn’t “remember” the format of the number you used, so if you assign a hex or octal value to a number, Perl will print the integer equivalent of them, but if you print a number using exponential format, Perl will only print the integer equivalent only if it can be represented without exponential notation (in other words, when it’s small enough).
We’ll see more about working with numbers in Chapter 4, Working With data.
Note
For more information, see perldoc perlnumber and perldoc perlfaq4 (Date Manipulation)
Arrays
In Perl, an array is an ordered list of scalars. Here’s how you might assign a few numbers to an array:
my @even = ( 2, 4, 6, 8, 10 );
Note
For more information, see perldoc perlintro.
For an array, the variable is preceded by an @ (at) sign, so the mnemonic for this is an “@rray”. And, when you have a list of items, separate them with a comma and use parentheses () around them. For now, just take my word for it. In Chapter 4, Working With data, you’ll learn more about this in a bit more detail when you discover precedence.
So, the preceding code has an array on the left and a list on the right, and you’re assigning the list to the array.
Of course, just as with scalars, you can use any kind of data you need to use. You can even assign lists with a mix of strings or other scalars to an array.
my $nine = 9; my @stuff = ( 7, 'of', $nine );
If you just print the array as shown in the following example, what happens?
my $nine = 9; my @stuff = ( 7, 'of', $nine ); print @stuff, "\n"; print "@stuff\n";
While there are ways you can tweak this, the example code just presented will probably print the following:
7of9 7 of 9
Breaking Down the Code Example
In the previous example, the print function takes a list of arguments. Consider the first print statement in the example:
print @stuff, "\n";
This tells Perl to dutifully print every item in the list, one after another, with the newline being printed last. Because no item in the list contains a space, they run together as they’re being printed.
The second version has the array being interpolated into a string.
print "@stuff\n";
When an array is interpolated into a string, the individual elements are, by default, separated with a single space, generating the “7 of 9” output.
Note
Although an array interpolated into a string is separated by default by a single space, this is actually controlled by the value of the $" special variable. You’ll want to read perldoc perlvar to understand this later. Some sloppy programmers like to abuse that variable and you’ll see it in code from time to time.
You might also note that the array @stuff has two integers and one string. Because Perl is more focused on data structures than strict limitations on the kinds of data they contain, you can generally use whatever kinds of data you want.
Accessing Elements
Now, printing out an array is all fine and dandy, but often when you’re working with an array, you are trying to work with one element of the array or all elements. (Sometimes you work with a few elements called a “slice,” and you’ll learn more about that in a bit.)
You may remember earlier in this chapter the discussion said that, “in Perl. when you see a variable beginning with a dollar sign, you know that you’re accessing a $calar value.” It’s the same with arrays. Arrays are indexed by number, with the first element of the array being indexed by 0 (zero). Getting that first element looks like this:
my @words = ("and", "another", "thing");
print $words[0];Remember that the sigil before the variable name indicates how you’re accessing it, not the type of variable. This is a frequent source of confusion for newer Perl programmers, so it’s important that you pay careful attention to this.
Also note on the right side of the variable name square brackets appear around the index. When you’re using square brackets in Perl, it usually means you’re dealing with an array (or possibly a reference to an array, but you’ll learn about that in Chapter 6, References).
Naturally, if you want to access all of the elements, you can do this:
my @words = ( "and", "another", "thing" ); my $first = $words[0]; my $second = $words[1]; my $third = $words[2];
As you might expect, you can also assign to individual elements of the array this way:
$words[1] = "one more"; print "@array\n";
That prints and one more thing.
Again, note that when accessing an individual element of an array, you have a dollar sign on the left and square brackets on the right. This will be repeated quite a bit. It’s one of the classic stumbling blocks for new Perl programmers. If your eyes glaze over and you stop reading about the sigils and things like that, it’s your own darn fault when you get them wrong!
Sometimes you’ll find that you want some trailing elements of an array, but you’re not sure of the length. It’s easy to find out the length of the array, but there’s actually an interesting trick here. If you access an array with a negative number, you access array elements from the end of the list going backward, starting with −1 (because 0 would be the first element).
my @words = ( "and", "another", "thing" ); my $last = $words[-1]; print $last;
That will print thing. Of course, $words[-2] would be another and $words[-3] would be and.
As a handy shortcut, so long as you’re assigning literals to the array and not variables, you can use the qw() operator (as in “q”uote “w”ords) like this:
my @odds = qw( 1 3 5 charlie );
The qw() operator takes a string and automatically separates it on whitespace, so this line of code is equivalent to the following:
my @odds = ( 1, 3, 5, 'charlie' );
Sometimes you’ll see something like this:
my @odds = qw( 1, 3, 5, 'charlie' );
That’s probably now what you want, and if you have warnings on, it will warn about a “Possible attempt to separate words with commas.” That’s because, since the string in the qw() operator is separated by whitespace, the commas will be included in the values and not be used as a list separator.
As with the qq() operator, qw() allows just about any pair of balanced delimiters. Some common ones include the following:
my @odds = qw! 1 3 5 charlie !;
my @odds = qw< 1 3 5 charlie >;
my @odds = qw{ 1 3 5 charlie };
my @odds = qw[ 1 3 5 charlie ];Those are useful in case one of the words in the string might other contain a delimiter, as shown here:
my @punctuation = qw[ . ; ! ( ) { } ];Iterating Over Arrays
Naturally, you don’t want to always access array data by assigning the value of different elements to different variables. You often want to iterate over the elements and do something with them. Here’s one way to do this (but Chapter 5, Control flow goes into more detail during a discussion of control flow):
my @array = ( 'this', 'is', 'an', 'array' );
for my $element (@array) {
print "$element\n";
}That should print the following:
this is an array
Hashes
Note
perldoc perlintro
One of the reasons Perl is so popular is because of how easy it is to sling data around. Hashes are a perfect example of this. A hash is sort of like an array, except that instead of indexing into the hash using integers, you use strings. You refer to the strings you index into the hash with as keys, and the values they return are, well, values.
Here’s a hash with three keys and their values:
my %people = (
"Alice", 1,
"Bob", 2,
"Ovid", "idiot",
);
print $people{'Alice'};You could simulate that with an array, but it would be clumsy and require a many almost useless variable declarations.
my @people = ( 1, 2, 'idiot' ); my $alice = 0; my $bob = 1; my $ovid = 2; print $people[$alice];
Accessing Elements
As you have already seen, accessing data in a hash is simple:
my %people = (
"Alice", 1,
"Bob", 2,
"Ovid", "idiot",
);
my $number = $people{'Bob'};
print "Bob = $number\n";
print "Bob = $people{'Bob'}\n";You’ll immediately notice a few things here. First, you can see that to access an individual element of the hash, you have a dollar sign for the sigil (see a pattern?) and curly brackets (“curly braces,” “curlies,” “squiggly braces,” or whatever the heck you call ‘em) around the index.
As mentioned, the “keys” of the hash correspond to an array’s numeric indices. In fact, you could do that if you wanted to like this:
my %french_word_for = (
1, 'un',
2, 'deux',
3, 'trois',
);
print "The French word for '3' is $french_word_for{3}\n";That can be confusing, and you probably just want an array itself (though if you have a sparse array, a hash might be a good choice).
You’ll also note that you retrieved the hash value without quoting the key:
my $french_word = $silly_example{3};
my $other_data = $another_example{some_key};When accessing a single value, you are not required to quote the key, so long as it follows the rule of an identifier. So, this is wrong, and you must quote the key:
my $other_data = $another_example{-some_key};Iterating Over Hashes
Iterating over a hash is fairly simple. One way to do this is to use the keys function. This returns the list of keys from the hash, as shown in the following example:
my %people = (
"Alice", 1,
"Bob", 2,
"Ovid", "idiot",
);
for my $name ( keys %people ) {
print "$name is $people{$name}\n";
}That might print something like this:
Ovid is idiot Bob is 2 Alice is 1
Note that the order of the hash keys is effectively random, so there’s no guarantee that your version of Perl will print those lines in this order. It’s actually not random, but the reasons for that are beyond the scope of this book. Just remember that you should never rely on hash order. However, you’ll learn more about that in Chapter 10, Sort, map and grep during a discussion of sorting.
There is a corresponding values function that returns the values of the hash, again without any predictable order.
Adding Data to Hashes
To add a new value to a hash, simply assign the new value to a key:
$people{Austen} = 'Jane';That will add a new value to the hash, or overwrite the value for the key Austen if it exists.
You can add multiple key/value pairs by assigning the hash and a list:
%people = ( %people, Austen => 'Jane', Lincoln => 'Abraham' );
If any of the keys in the list match keys in the original hash, the original values will be replaced with the new ones.
Slices
In Perl, A slice is a way of selecting a few elements of an array, list, or hash.
Array Slices
You’ve already learned that “the sigil that starts the variable indicates how you’re accessing it,” so as you might guess, to take several elements out of an array at once, you use the @ sign at the front. Following is an example:
my @names = ('Alice', 'Bill', 'Cathy', 'Doug');
my @men = @names[ 1, 3 ]; # Bill and Doug
my @women = @names[ 0, 2 ]; # Alice and CathyNote
For more information, see perldoc perlintro.
It’s the square brackets ([]) that tell you what type of variable you’re indexing into (an array, in this case), not the leading sigil. Again, this is a concept you’ll need to get very used to because it’s core to understanding the Perl language. And, yes, this drum is being beaten repeatedly because everyone gets it wrong sooner or later.
Generally, it doesn’t make sense to take a single-element slice. So, if you do this, you get a warning (if you have warnings enabled, which you’ll learn more about in a bit).
use warnings;
my @stuff = ('bits', 'and', 'bobs');
my $item = @stuff[1];
print $item;That will issue the following warning:
Scalar value @stuff[1] better written as $stuff[1] at stuff.pl line 3.
Make that recommended change and the warning will go away.
Hash Slices
Naturally, you can take a slice of a hash. Because you use the leading sigil to indicate how you’re accessing the variable, you use the @ sign again, but with curly braces. Following is an example:
my %nationality_of = (
'Ovid' => 'Greek',
'John Davidson' => 'Scottish',
'Tennyson' => 'English',
'Poe' => 'Tacky', # Geek?
);
my @nationalities = @nationality_of{ 'Ovid', 'Tennyson' };
print "@nationalities";That will print “Greek English,” despite the fact that Ovid was actually a Roman poet. Garbage in, garbage out.
Context
Context is one of the more unusual and useful features of Perl. Context means an expression can change its value based on what the calling code expects to receive. This sounds strange, and some new programmers — not you, of course — get confused by it. Once you get used to it, you’ll find it very easy and natural. Take care to understand this concept because you’ll see it constantly in Perl programs.
Note
For more information, see perldoc perlglossary.
There are three main types of context: scalar, list, and void. They often mean “what the left side of an expression wants to get.” Rather than belabor this, following are some examples of this beautiful craziness.
Scalar Context
Following is an example of scalar context:
my $number_of_things = @things_in_common; my $number_of_things = scalar @things_in_common; my $number_of_things = ( 'liars', 'fools', 'certain politicians' ); my $number_of_things = %hash_example;
When dealing with assigning values to variables, what you have on the left side of the = determines the “context” on which you’re evaluating the right side. So, if you have a scalar on the left, you have scalar context.
Arrays in Scalar Context
Following is an example of an array in scalar context:
my @things_in_common = ( 'liars', 'fools', 'certain politicians' ); my $number_of_things = @things_in_common;
As you might guess from the variable name, $number_of_things is equal to 3, the number elements in @things_in_common. That’s because the scalar context value of an array returns the number of elements in that array.
If you want to force scalar context, you can use the scalar keyword, as shown here:
my @things_in_common = ( 'liars', 'fools', 'certain politicians' ); my $number_of_things = scalar @things_in_common;
That last line has exactly the same meaning with or without the scalar keyword, but it does make it very explicit that you meant scalar context and weren’t trying to assign an element of the array to $number_of_things.
The scalar keyword is also essential when you want to force scalar context and not list context. So, the following is probably not correct:
my @things_in_common = ( 'liars', 'fools', 'certain politicians' );
my %count_for = ( useless_things => @things_in_common );
print $count_for{useless_things};With a comma operator, whether you’re dealing with the regular comma or the “fat comma” (=>), you are using list context, so you can fix the previous snippet with the scalar keyword, as shown here
my @things_in_common = ( 'liars', 'fools', 'certain politicians' );
my %count_for = ( useless_things => scalar @things_in_common );
print $count_for{useless_things};Note
See perldoc -f scalar for more information.
Lists in Scalar Context
If you force scalar context with a list (again, an array is a container for a list), whatever is on the left side of each comma is evaluated, the result is thrown away, and the right-hand side is evaluated. That leads to common errors like this:
my $number_of_things = ( 'liars', 'fools', 'certain politicians' ); print $number_of_things;
That prints certain politicians instead of the number 3. Thus, you usually don’t want to use a list in scalar context; use an array instead.
Hashes in Scalar Context
Naturally, you can also use scalar context with a hash, as shown here:
my %hash = ( 1 => 2 ); print scalar %hash;
However, that’s probably going to print something like 1/8, and that’s about as useful as an ashtray on a motorcycle. In scalar context, you’re actually seeing a bit about the internal structure of the hash. It has its uses, but they won’t be covered here.
List Context
You have list context when the left-side value expects a list. Here’s how to copy an array to another array:
my @copy = @old_array;
Note that this is a “shallow” copy in that you’re only copying the top-level elements. Later, when you learn about references (Chapter 6, References), you’ll learn about this in more detail.
If you want, you can also assign a hash to an array, as shown here:
my %order_totals = (
Charles => 13.2,
Valerie => 17.9,
'Billy Bob' => 0,
);
my @flattened = %order_totals;That “flattens” the key/value pairs in the hash into a list. If you print the resulting array, you might get something like this:
Billy Bob 0 Charles 13.2 Valerie 17.9
Again, this is because a hash is not ordered. If you need to retrieve the elements of a hash in order, see Chapter 10, Sort, map and grep, which explores sorting.
One of the nice things about list context is that you can force it with parentheses. For example, if you want to assign the first element of an array to a scalar, just put parentheses around the scalar, as shown here:
my @swords = ( 'katana', 'wakizashi' ); my $number_of_swords = @swords; my ($left_hand) = @swords;
However, you aren’t limited to a single scalar. You can assign several scalars at the same time, as shown here:
my ( $left_hand, $right_hand ) = @swords;
This will come in extremely handy when you learn more about subroutines in Perl.
This has an interesting side effect. When you’re facing down Toshiro Mifune and you realize that your katana and wakizashi swords are in the wrong hands, you’re in trouble. Here’s how you might do that in C:
char *other_hand; strcpy( other_hand, left_hand ); strcpy( left_hand, right_hand ); strcpy( right_hand, other_hand );
Too bad. You’re dead.
In Perl, because you can use list context with those scalars, you can just do this:
( $right_hand, $left_hand ) = ( $left_hand, $right_hand );
Pretty handy, eh?
You can mix scalars and other variables with this:
my ( $first, @extra ) = ( 1, 2, 3 4 );
$first will have the value of 1 and @extra will be 2, 3, and 4. However, the scalars must come first!
my ( @extra, $last ) = ( 1, 2, 3 4 );
That doesn’t do what you want because @extra slurped up all of the values and $last will be undefined.
Now it’s time for you to get some experience actually working with these variables yourself.
Scope
Now it’s time to talk about scope. No, this is not about the mouthwash, but rather the “scope” of variables, or “where you can see them from.”
Note
For more information, see perldoc perlintro.
my Variables
Variables declared with my are referred to as “lexically scoped.” This means that they do not exist outside of the scope in which they are declared. This generally means file scoped or block scoped.
File scoped means that any my variable declared outside of a block is visible from that point on to the end of the file in which it is declared. This also means that if you have several packages in a file (which you’ll learn about in Chapter 11, Packages and Modules), the my variable in question will be visible to all packages in that file. You generally want to avoid that.
However, if they are declared inside of a block, they remain scoped to that block. In Perl, a block is simply one or more Perl statements delimited by curly braces. For example, here’s a bare block:
my $answer = 42;
{
my $answer = 'forty-two';
print "$answer\n";
}
print "$answer\n";That will print the following:
forty-two 42
This is because the my declaration inside of the block “hides” the variable from the scope outside of the block.
Note
You cannot declare Perl’s built-in variables like this, with one exception. Prior to version 5.10, you were not allowed to do the following, even though it appeared to obey the rules:
my $_;
That was not allowed because $_ is one of Perl’s built-in special variables, which you’ll learn about later in this chapter. As of version 5.10 and after, this restriction has been lifted, and you are allowed to use my $_, but not for the other built-ins. See perldoc perl5100delta and search for “Lexical $_” for more information.
Example 3.1, “Variable scoping in blocks” provides a more real-world example with a block in a for loop.
Example 3.1. Variable scoping in blocks
use strict;
use warnings;
use diagnostics;
my @numbers = ( 1, 2, 3, 4, 5 );
for my $number (@numbers) {
my $reciprocal = 1 / $number;
print "The reciprocal of $number is $reciprocal\n";
}
print $number;
print $reciprocal;Note
listing_3_1_scope.pl available for download at Wrox.com.
The program in Example 3.1, “Variable scoping in blocks” will not run. Instead, you’ll get a bunch of errors similar to the following:
Global symbol "$number" requires explicit package name at numbers.pl line 11. Global symbol "$reciprocal" requires explicit package name at numbers.pl line 12. Execution of /var/tmp/eval_NAVl.pl aborted due to compilation errors (#1) (F) You've said "use strict" or "use strict vars", which indicates that all variables must either be lexically scoped (using "my" or "state"), declared beforehand using "our", or explicitly qualified to say which package the global variable is in (using "::"). Uncaught exception from user code: Global symbol "$number" requires explicit package name at numbers.pl line 11. Global symbol "$reciprocal" requires explicit package name at numbers.pl line 12. Execution of $numbers.pl aborted due to compilation errors.
The @numbers variable does not appear in the error message because it’s file scoped and thus visible everywhere in this file. The error is because the $reciprocal and $number variables are declared with my inside of the block and are not available outside of it. Note that the $number variable is also lexically scoped to that block, even though it might appear to be outside of it. That’s just how for loops work.
To make the broken code run, simply delete the two print statements after the for loop.
But you may have noted the “requires explicit package name” error highlighted in the previous error message. What exactly does that mean?
Package Variables
In Perl, a package is just a “namespace” to keep variables, subroutines, and other things organized. By default, things live in the package main. You declare what package (namespace) you’re in with the package keyword. You’ll learn about this more in-depth in Chapter 11, Packages and Modules, but for now, when you’re writing simple programs, you only need to know the basics.
Generally you’ll find that package variables are globally scoped. A globally scoped variable is available anywhere in your program.
Note
A namespace is just a place where any names used won’t show up in another namespace. They’re a convenient way to organize your code. You’ll find more in-depth coverage of this in Chapter 11, Packages and Modules.
Consider the following code:
package main; use strict; use warnings;
Here, the package main; statement isn’t really required, because main is the default package. However, sometimes you’ll see code written like this:
package MyCompany::Stuff;
use strict;
use warnings;
%MyCompany::Stuff::department_number_for = (
finance => 13,
programming => 2,
janitorial => 17,
executive => 0,
);And later, other code can reference this with the following:
my $department_number = $MyCompany::Stuff::department_number_for{finance};It doesn’t matter if that code is in the same package, or even a different file, so long as the MyCompany::Stuff package has been loaded. When addressing a package variable with the full package name included in it, this is known as a “fully qualified variable.” However, typing $MyCompany::Stuff::department_number_for{finance} can be very annoying. It’s also error-prone because the following is legal, but probably not what you intended (note the misspelling of “Sutff”):
my $department_number = $MyCompany::Sutff::department_number_for{finance};Thus, you have several options to deal with this. One is to not use the strict pragma. (A pragma is a special module, the name of which is usually written in all lowercase letters, which alters the compile or runtime behavior of your program.) Any variable referenced without the my function is automatically a variable in the current package.
package main; $answer = 42 print "$anwser\n";
That’s legal Perl, but you can see how easy it is to misspell variable names, so you shouldn’t do that because that way lies madness.
The vars Pragma
Moving along, prior to Perl 5.6.0, you had the vars pragma and it looked like Example 3.2, “The vars pragma”.
Example 3.2. The vars pragma
package MyCompany::Stuff;
use strict;
use warnings;
use vars (
'%department_number_for',
'$some_other_package_variable',
);
%department_number_for = (
finance => 13,
programming => 2,
janitorial => 17,
executive => 0,
);
$some_other_package_variable = 42;
print $department_number_for{finance};Note
listing_3_2_vars.pl available for download at Wrox.com.
Outside of the package, you would still have to refer to those variables by the fully qualified variable names, and, thus, run the risk of typos, but it saves typing inside of the package.
Declaring Package Variables with our
However, starting with version 5.6.0, Perl introduced the our function. Unlike the my function that says “this variable is mine,” the our variable says “this variable is ours.” In other words, it’s like any other package variable, but it has a cleaner syntax.
Example 3.3, “Declaring variables with our” shows an example with the our function.
Example 3.3. Declaring variables with our
package MyCompany::Stuff;
use strict;
use warnings;
our %department_number_for;
our $some_other_package_variable;
%department_number_for = (
finance => 13,
programming => 2,
janitorial => 17,
executive => 0,
);
$some_other_package_variable = 42;
print $department_number_for{finance};Note
listing_3_3_our.pl available for download at Wrox.com.
Many people have a habit of declaring variables with the vars pragma or with the our function. Do not do this unless you really need to share that variable outside of your package. When someone else’s code changes that variable’s value and breaks your code, it can be very difficult to track down.
Using Local Variables
Of course, sometimes you want to limit the scope of your package variables. You can’t use the my keyword to declare them, but you can use local to make it clear that they’re “localized” to a given scope. Following is an example:
our $answer = 42;
{
local $answer = 57;
print "$answer\n";
}
print "$answer\n";That will print the following:
57 42
Whenever you need to temporarily change the value of a package variable, use the local function. Of course, you can do this with fully qualified variable names, too, as shown here:
local $MyCompany::Stuff;
That ensures that you can do just about anything you want with $MyCompany::Stuff in your local scope without causing problems for others who rely on the original value.
If you need to keep the original value and change it, assign it to itself with local, as shown here:
our $answer = 42;
{
local $answer = $answer;
print "$answer\n";
$answer = $answer + 2;
print "$answer\n";
}
print "$answer\n";That prints the following:
42 44 42
Be sure you understand why that works because it’s a common idiom in Perl.
strict, warnings, and diagnostics
Before we go much further, we need to stop for a word from our sponsors, strict, warnings, and diagnostics.
Strictly speaking you don’t need the my in front of a variable declaration. Or perhaps that should read “unstrictly” speaking. For most experienced Perl programmers, you’ll see the following two lines at the top of virtually all of their Perl programs:
use strict; use warnings;
And, when you’re new to Perl, adding the following line is also recommended:
use diagnostics;
strict, warnings, and diagnostics are called pragmas. As mentioned earlier, in Perl, a pragma is a special module, the name of which is usually written in all lowercase letters, which alters the compile or runtime behavior of your program.
Of course, you can generally leave these pragmas out when writing your software, but it’s a bad idea, and many Perl developers will not help you if you omit these things. Why? Because they save so much development by protecting you from silly mistakes that you’d be insane to not use them. You’re not insane, are you? (Hmm, you are learning Perl, though).
If you really need to, you can turn these off, as shown here:
no strict; no warnings;
However, if you do so, it’s recommended that you only do so with two conditions:
It’s a limited scope.
You only turn off the bits you need.
{
no warnings 'uninitialized';
$total = $total + $some_value;
}In the preceding code example, $total might be accumulating some your order total, but sometimes $some_value might be allowed to be undefined. In that case, you might decide it’s okay to turn off “uninitialized” warnings in that scope. (Good luck spelling “uninitialized” right the first time, by the way.).
Note
You should read perldoc strict and perldoc warnings to better understand how they work and what bits you can turn off. perldoc perllexwarn goes into extensive detail about how the warnings pragma is structured.
You’ll see more examples later in the book, but there’s no point in covering them in-depth now. By the time you really understand them, you’ll be better prepared to understand why to do this.
Now, let’s look at the individual pragmas to see the basics.
strict
For strict, you could actually write the following:
use strict 'vars'; use strict 'subs'; use strict 'refs';
However, you usually just want to write this (which means the same thing):
use strict;
Later in this book you’ll discover when you need to change this, but there is no point in teaching you how to use a gun until you’re old enough to decide for yourself if you really want to shoot yourself in the foot. (Actually, it’s just that it’s a bit too much right now.)
The vast majority of the time, strict means “predeclare your variables.” If you forget to do so, your program will not even run. For example, say that you try to do this:
my $name = 'Danny'; my $nick = $naem;
You will get a compile-time error because you misspelled $name (unless you created my $naem for some reason).
warnings
For warnings, things are a bit different. They’re generally just warning you about bad things your program is doing. But, in reality, these things might be okay. Your program will run, but warnings will be printed when your code thinks you’re doing something dodgy. You should look at the warnings closely to find out what they actually mean. For example, if you have warnings enabled, the following code will generate a warning about an uninitialized value in addition:
use warnings; my $x; my $y = $x + 2;
For versions of Perl prior to 5.6.0 (and sometimes after, for backward-compatibility), you’ll often see the -w switch (see perldoc perlrun) on the shebang line instead:
#!/usr/bin/perl -w use strict;
This is because the warnings pragma was introduced in version 5.6.0. If you have the misfortune of working with an older version of Perl, be aware that 5.6.0 came out in 2000. In terms of technology, it’s ancient, and is no longer supported.
diagnostics
If you’re relatively new to Perl, you should also use the diagnostics pragma, as shown in Example 3.4, “Using diagnostics”. This gives long-winded explanations of why you’ve been so naughty. The masochists will love it.
Example 3.4. Using diagnostics
use strict; use warnings; use diagnostics; my $x; my $y = $x + 2;
Note
listing_3_4_diagnostics.pl available for download at Wrox.com.
The program shown in Example 3.4, “Using diagnostics” will print out a much longer diagnostic method to help you understand not only what went wrong, but why. Reading through these diagnostic messages is a great way to understand what Perl is doing and why. Following is an example:
Use of uninitialized value $x in addition (+) at diag.pl line 5 (#1) (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl will try to tell you the name of the variable (if any) that was undefined. In some cases it cannot do this, so it also tells you what operation you used the undefined value in. Note, however, that perl optimizes your program and the operation displayed in the warning may not necessarily appear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer to the concatenation (.) operator, even though there is no . in your program.
As you can see, the diagnostic information is fairly good. If you (unlike the vast majority of programmers out there) actually read your errors and warnings carefully, you’ll have no problem understanding what happened.
Warning
Unfortunately, for versions of Perl prior to 5.10.0, you won’t see the name of the variable in this warning. This meant that warnings from long strings with many interpolated variables were a nightmare. Now they’re just an annoyance.
Working Without a Net
You might think that strict and warnings aren’t that important, but consider the following example:
$disarm_nuclear_weapon = true;
Without strict, a bareword (a string literal without quotes) is just a string. That snippet might assign the string true to $disarm_nuclear_weapon. However, some terrorist programmer who has read Chapter 7, Subroutines on subroutines might add this above that line:
sub true { 0 }And now you’ve assigned a false value (see Chapter 5, Control flow) to $disarm_nuclear_weapon and started World World III. Thanks a lot buddy! Just use strict and warnings, and keep the world safe from terrorism!
Now let’s get some hands-on experience with uninitialized variables.
Perl’s Built-in Variables
Perl has many special built-in variables that are global in scope. Though the number of these variables can seem bewildering at first, the common built-in variables are easy to memorize and can be used to make your life simpler, including handling some common tasks that other languages might require a library or extra code to handle. We will generally introduce these special variables as the need arises, but a few deserve special mention up front.
$_
One of the most common special variables is the $_ variable, sometimes referred to as “dollar underscore.” This is the “default” variable and many functions automatically operate on this.
Note
For more information, see perldoc perlvar.
For example, when iterating over an array, you can do this:
for my $element (@array) {
print $element;
}Or, you can do this:
for (@array) {
print "$_\n";
}That’s because, when you use a for loop and you don’t create a variable to assign the elements to, the $_ variable is automatically populated with the value. In fact, the print function, by default, prints the $_ variable if it doesn’t have any arguments, as shown here:
for (@array) {
print;
}That will print all of the elements on a single line and you probably don’t want that. Instead, if you’re using Perl 5.10 or newer, you can use the feature pragma to import the say function. say is just like print, but it automatically adds a newline to whatever you print. Like print, it will automatically use the value of $_ as an argument if no arguments are provided.
use feature 'say';
for (@array) {
say;
}%ENV
The global %ENV hash contains environment variables. These are variables generally set outside your program, but your program can read them to modify its behavior. For example, the $ENV{HOME} environment variable, on most operating systems, contains the home directory of the current user who is running the program.
Setting an environment variable in your program will not cause your operating system to see the new value, but all other parts of your program will see it. As this is a global variable, use with care.
@ARGV
Another useful built-in variable is @ARGV. This built-in array contains the arguments passed in on the command line. Example 3.5, “Rewriting “Hello, World!” with @ARGV” shows a way you can rewrite “Hello, World!”, but take the arguments from the command line:
Example 3.5. Rewriting “Hello, World!” with @ARGV
use strict; # yes, I use these even for short programs use warnings; print "Hello, @ARGV";
Note
listing_3_5_hello.pl available for download at Wrox.com.
Save that as hello.pl and type this on the command line:
perl hello.pl John Q. Public
That should print out Hello, John Q. Public.
Note
If you pass no arguments to the hello.pl program, you won’t get an uninitialized warning because empty arrays are simply empty. There are no uninitialized values present.
There are plenty of other special variables in Perl, and you’ll learn about some of them as this book progresses. For now, you can read through perldoc perlvar and weep or laugh. Fortunately, you won’t encounter most of them.
Other Special Variables
As mentioned, Perl has many special variables built in to the language. Table 3.3, “Common Special Variables” lists a few of them. Don’t worry about their meaning for now, just be aware they exist. New ones will show up from time to time throughout the book.
Table 3.3. Common Special Variables
Variable | Description |
|---|---|
| Parameters passed to a subroutine. |
| The name of your program. |
| Special global variables used in sort subroutines. |
| Hash containing your environment variables. |
| Contains paths to look for files loaded with |
| Contains entries for every file loaded with |
| The current Perl version (Perl 5.6.0 or later). |
| The executable used to execute your program. |
| Subpatterns extracted from regular expressions (Chapter 8, Regular Expressions). |
| Value of system error calls. |
| Perl syntax error trapped by eval. |
Note
You should read perldoc pervar for more information.
Exercises
What some differences between
strictandwarnings?Create an array with the values “Andrew,” “Andy,” and “Kaufman” (without the quotes). Write a program that will print:
Andrew "Andy" Kaufman.Create a hash with the keys being names of fruits and the values being their normal color. Print every key/value pair as a separate line similar to
bananas are yellow.
WHAT YOU LEARNED IN THIS CHAPTER
Topic | Key Concepts |
|---|---|
Scalars | A container for a single value. |
Arrays | A container for a list of values. |
Hashes | A unordered container for key/value pairs. |
Slices | Extracting a subset of data from arrays and hashes. |
Scope | Where you can “see” variables. |
Lexical variables | Variables restrict to a given scope. |
Package variables | Variables associated with a given package. |
Built-in variables | Special variables built into the language. |
Context | How a given expression is evaluated. |
| A pragma to require variable declaration. Also used to prevent certain unsafe behaviors with references and subroutines. |
| A pragma to warn about unsafe behaviors. |
| A pragma to provide verbose explanations of errors and warnings. |
Answers
Chapter 3 Exercise Answers
Following are the answers to the exercises in Chapter 3, Variables.
Answer to Question 1
The major differences between strict and warnings is that strict will prevent your program from running when it encounters some unsafe code, such as using an undeclared variable.
In constrast, warnings, will not prevent your program from running, but will instead emit “warnings” when your code exhibits behavior which may be problematic, such as when you attempt to use an unintialized variable or try to add a number to a string.
Answer to Question 2
Following is an example of creating an array with the values “Andrew,” “Andy,” and “Kaufman” (without the quotes) and writing a program that will print: Andrew "Andy" Kaufman:
use strict;
use warnings;
use diagnostics;
my @name = qw(Andrew Andy Kaufman);
print qq{$name[0] "$name[1]" $name[2]\n};Note
exercise_3_2a_array.pl available for download at Wrox.com.
Another way to accomplish this is the following:
use strict;
use warnings;
use diagnostics;
my @name = ('Andrew', 'Andy', 'Kaufman');
my ( $first, $nick, $last ) = @name;
print qq{$first "$nick" $last\n};Note
exercise_3_2b_array.pl available for download at Wrox.com.
Answer to Question 3
Following is an example of how to create a hash with the keys being names of fruits and the values being their normal color, and then printing every key/value pair as a separate line similar to bananas are yellow:
use strict;
use warnings;
use diagnostics;
my %color_for = (
bananas => 'yellow',
apples => 'red',
oranges => 'orange',
);
for my $fruit (keys %color_for) {
my $color = $color_for{$fruit};
print "$fruit are $color\n";
}Note
exercise_3_3_fruit.pl available for download at Wrox.com.





Add a comment



Add a comment