Полезная информация

Advanced Perl Programming

Advanced Perl ProgrammingSearch this book
Previous: 1.4 Querying a ReferenceChapter 1
Data References and Anonymous Storage
Next: 1.6 A View of the Internals
 

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


Previous: 1.4 Querying a ReferenceAdvanced Perl ProgrammingNext: 1.6 A View of the Internals
1.4 Querying a ReferenceBook Index1.6 A View of the Internals