Seitenanfang

Perl variable declaration secrets

Perl has a very flexible variable concept. One might use different namespaces, called "packages" or use all variables global without defining them. Another way to use variables is more Cish where every single variable must be declared before it's used.

Perl_Variables.pngThere is no need to enforce the declaration of every variable, but it's considered good practice. Perl requires only one line to switch Perl to strict mode where every used, but undeclared variable will trigger a fatal error:

use strict;

Global variables may still be defined using the our keyword:

our $GLOBAL_VAR;
our %SOME_HASH = (foo => 1);

I prefer to use only uppercase chars for global variables to clearly distingush them from local ones, but that's only a personal preference and no Perl requirement.

Variables limited to some scope use the my keyword:

sub foo {
my $bar;
my @baz = (1,2,3);
}

my-variables only exist until the end of the current block including any sub-blocks:

sub foo {
my $bar = shift; # Grab first arg of sub-call
if ($bar) {
my $baz = $bar + 1;
print "$bar + 1 = $baz";
}
}

The $bar is visible to the whole sub including the inner part of the if block. $baz is only visible to the inner block, because it's defined there. Using $baz within the sub but outside the if block will trigger an error (if use strict is in place) or at least not use the same variable as within the if:

sub bar {
my $foo = 1;
if ($foo) {
my $foo = 2;
print $foo;
}
print $foo;
}

This example is bad practice, because it's (heavily) reusing variable names! But it's working. The first $foo is defined for the whole sub, but the second one exists within the if block, no matter that both of them are using the same name. A call to this sub will print "2" and then "1", because the first print is using the innermost $foo (which has been initilized with a value of "2") and the second print will use the only $foo which is valid at this point: The one defined for the whole sub with a value of "1".

Reusing variable names is still not good, but there is a special tweak for using variables in the same line where they are defined:

sub baz {
my $foo = 1;
if ($foo) {
my $foo = $foo + 1;
print $foo;
}
}

The print statement will clearly see the inner variable, but it's defined once the my statement has been processed. Think of the my $foo as some kind of special function call: All  arguments are calculated before the function is called. The green (outer) $foo is used on the right side of the equal sign "=" in this case, because this part has to be completed first, before the final result value could be assigned to the newly created inner (blue) $foo.

Everything shown here is also valid for arrays and hashes, not only for scalars.

 

Noch keine Kommentare. Schreib was dazu

Schreib was dazu

Die folgenden HTML-Tags sind erlaubt:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>