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'.

Get Advanced Perl Programming now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.