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.