The Basics: A General Overview of How to Use References

Let's look at a few simple examples of creating and using references so you can get a feel for the technique. Perl actually has a number of ways of working with references, but here we'll focus on the easiest and most popular mechanisms, and explore the others in a later section (“Other Ways of Using References”).

Creating a Reference

Start with something you've seen a gazillion times before in this book: A plain old scalar variable that contains a string.

$str = "This is a string."

This is an ordinary scalar variable, holding ordinary scalar data. There's some location in memory that stores that string, which you can get to through the $str variable name. If you assigned something else to $str, the memory location would have different contents and there would be a different value for $str. All this is the basic stuff you've been doing all along.

Now let's create a reference to that data. To create a reference, you need the actual memory location of the data in question (a scalar, an array, a hash, or a subroutine). To get at that memory location, you use the backslash () operator and a variable name:

$strref = $str;

The backslash operator gets the memory location of the data stored in $str and creates a reference to that location. That reference then gets assigned to the scalar variable $strref (remember, references are a form of scalar data).

Note

The backslash operator is very similar to the address (&) operator in C. Both are used to access the actual memory location of a piece of data.


At no point here do the actual contents of $str—the string “This is a string.”—come into play. The reference doesn't care about the contents of $str, just its location. And $str remains a scalar variable containing a string; the reference's existence doesn't change anything about that either. (See Figure 19.1.)

Figure 19.1. A variable, a string, and a reference.


This example created a reference to a string. But you can also create references to arrays, hashes, or subroutines—anything that has a memory location in Perl. For example, here's a reference to an array:

@array = (1..10);
$arrayref = @array;

And here's one for a hash:

%hash = (
   'red' => '0 0 255',
   'green' => '0 255 0',
   'blue' => '255 0 0; );
$hashref = \%hash;

As with the reference to a scalar value, the array and hash in these examples remain arrays and hashes stored in the @array and %hash variables, respectively. And the array and hash references in $arrayref and $hashref are bits of scalar data, regardless of the data they point to. The most important thing to remember here is that the reference itself is a scalar. The thing it points to can be any kind of data.

Note

You can also create references to subroutines. Because this is an advanced topic, and not as commonly used as references to scalars, arrays, and hashes, we'll look at references to subroutines and how they're used in this lesson's “Going Deeper” section.


Printing and Using References

So now you've created a reference with the backslash operator and stored it in a scalar variable. What do these references look like? They're scalars, and as such can be used anywhere a scalar can, and as with numbers and strings they behave differently based on context.

A reference used as a string indicates the data it refers to (a scalar, an array, a hash, and so on), and a hexadecimal number representing the internal memory location the reference points to. So, for example, if you did this:

print "$strref
";

You'd get something like this:

SCALAR(0x807f61c)

The equivalent for $arrayref and $hashref would look like this:

ARRAY(0x807f664)

HASH(0x807f645)
						

Using a reference in a numeric context gives you the same hexadecimal number that you get when you use the reference in a string context, representing the memory location of the thing the reference points to. The numbers in both the string and number representations of the reference will vary depending on when you run the script and the memory that's free for Perl to use at that time. You wouldn't want to rely on those numbers; just consider that to be an internal representation of where the reference points.

Other uses of references? You can assign them to scalar variables, as we have here, use them as list elements, or store them in arrays and hashes (although they cannot be used as hash keys—more about this later). A reference, when used as a test, will always be true. But the most typical thing you do with references is to dereference them to gain access to the data they point to.

Dereferencing References

When you dereference a reference, you get at the data that reference points to. You could also think of it as following the reference, or accessing the location the reference refers to. But the term dereference is what is most commonly used.

There are a number of ways to dereference a reference, but the easiest way is to substitute the reference's scalar variable where a plain variable name would be expected, like this:

$originalstr = $$strref;

Two dollar signs? Yes. A single dollar sign is just the scalar variable $strref, which gives you the reference itself. The double dollar sign says “give me the thing that $strref points to.” In this case, the thing that $strref points to was the original string “This is a string.” You could think of two dollar signs as putting the reference—$strref—in place of the actual name of the variable you want to access.

To follow an array reference and gain access to the array itself, you'd do the same thing with an @ sign instead, and the $arrayref goes where the name of the array would be

@firstlist = @$arrayref;

The contents of @firstlist will now be that initial array we created and that $arrayref pointed to (actually, it'll be a copy of all the elements of that array).

Need to gain access to an actual array element from a reference? No problem. It's the same rule, just put the variable holding the reference where the name of the array would be

$first = $$arrayref[0];

Same rule for getting the topmost index number of an array:

$index = $#$arrayref;

Hashes work similarly:

%newhash = %$hashref;  # copy what $hashref points to
$value = $$hashref{red} ;  # get the value for the key "red"

@keys = keys %$hashref;   # extract keys
						

Changing Referenced-To Data

Here's the tricky part of references: changing the data that the reference points to. Say you've got your $strref as before, but then you change the value of $str later:

$str = "This is a string."
$strref = $str;
...
$str = "This is a different string."

What happens to the reference $strref? It continues to exist. It continues to point to that same memory location named by $str. If you dereference it, you'll now get the new string:

print "$$strref
";   # results in "This is a different string."

The reference itself doesn't care about the contents of the thing it points to, just the location. You can merrily change the contents all you want—the reference will just keep pointing to that same spot. Each time you dereference it, you'll get the thing contained at that location.

Note that this is different from regular variable assignment, which copies the contents of one memory location to another. References always continue to point to the same locations, and the contents can be changed out from under that reference. Take, for example, these statements:

@array1 = qw(ready set go);
@array2 = @array1;
$arrayref = @array1;
push @array1, "stop";

$, = ' ';  # set the array element delimeter
print "@array1
";
print "@array2
";
print "@$arrayref
";

Can you guess what will get printed in each of the three print statements? The contents of @array1 were created in the first statement, and then changed in the fourth, so the printout of @array1 will be this:

ready set go stop

@array2 was assigned to the contents of @array1 in the second line. With list assignment, the array on the right is expanded into its component elements, and then those elements are assigned to the array on the left. So, @array2 gets a copy of @array1 at that time and will print like this:

ready set go

Modifying @array2 has no effect on @array1; they are now separate arrays with separate contents.

The reference to @array1 in $arrayref, however, will be the same as the current contents of @array1 because the reference points to the same memory location as @array1 does. Printing that dereference, then, will result in this:

ready set go stop

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset