home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

1.5 Symbolic References

Normally, a construct such as $$var indicates that $var is a reference variable, and the programmer expects this expression to return the value that was pointed to by $var when the references were taken.

What if $var is not a reference variable at all? Instead of complaining loudly, Perl checks to see whether $var contains a string. If so, it uses that string as a regular variable name and messes around with this variable! Consider the following:

$x = 10;
$var = "x";
$$var = 30;   # Modifies $x to 30 , because $var is a symbolic
              # reference !

When evaluating $$var , Perl first checks to see whether $var is a reference, which it is not; it's a string. Perl then decides to give the expression one more chance: it treats $var 's contents as a variable identifier ( $x ). The example hence ends up modifying $x to 30.

It is important to note that symbolic references work only for global variables, not for those marked private using my .

Symbolic references work equally well for arrays and hashes also:

$var = "x";
@$var = (1, 2, 3);   # Sets @x to the enumerated list on the right

Note that the symbol used before $var dictates the type of variable to access: $$var is equivalent to $x , and @ $var is equivalent to saying @ x .

This facility is immensely useful, and, for those who have done this kind of thing before with earlier versions of Perl, is much more efficient than using eval . Let us say you want your script to process a command-line option such as " -Ddebug_level=3 " and set the $debug_level variable. This is one way of doing it:

while ($arg = shift @ARGV){
    if ($arg =~ /-D(\w+)=(\w+)/) {
         $var_name = $1; $value = $2;
         $$var_name = $value;     # Or more compactly, $$1 = $2;

On the other hand, Perl's eagerness to try its damnedest to get an expression to work sometimes doesn't help. In the preceding examples, if you expected the program logic to have a real reference instead of a string, then you would have wanted Perl to point it out instead of making assumptions about your usage. Fortunately, there's a way to switch this eagerness off. Perl has a number of compile-time directives, or pragmas. The strict pragma tells Perl to do strict error checking. You can even enumerate specific aspects to be strict about, one of which is `refs':

use strict 'refs';  # Tell Perl not to allow symbolic references
$var = "x";
$$var = 30;

This results in a run-time error whenever you try to use a symbolic reference:

Can't use string ("x") as a SCALAR ref while "strict refs" in use at try.pl line 3

The strict directive remains in effect until the end of the block. It can be turned off by saying no strict or, more specifically, no strict 'refs' .