Variables and Arguments in Perl

In this fifth part to a six-part article series on subroutines and functions in Perl, you’ll learn about lexical variables, and how passing arguments works. This article was excerpted from chapter six of the book Beginning Perl, Second Edition, written by James Lee (Apress; ISBN: 159059391X).

Lexical Variables (aka Local Variables)

The range of effect that a variable has is called its scope, and lexical variables declared with my() are said to have lexical scope. This is also known as local scope. That is, they exist from the point where they’re declared until the end of the enclosing block. The name “lexical” comes from the fact that they’re confined to a well-defined chunk of text.

my $x;
$x = 30;
{
my $x; # New $x
$x = 50;
# We can’t see the old $x, even if we want to.
}
print $x; # This $x is, and always has been, 30.

Great. We can now use variables in our subroutines in the knowledge that we’re not going to upset any behavior outside them. Let’s modify global2.pl by adding my() in the function (now called change_global_not() ):

#!/usr/bin/perl -w
# my.pl

$x = 10;

print “before: $xn”;
change_global_not();
print “after: $xn”;

sub change_global_not {
my $x = 20;
print “in change_global_not(): $xn”;
}

This gives us the output we expect:

$ perl my.pl
before: 10
in change_global_not(): 20
after: 10
$

{mospagebreak title=Some Important Notes on Passing Arguments}

Sometimes we want to pass things other than an ordinary list of scalars, so it’s important to understand how passing arguments works.

Function Arguments Passed by Reference

An important thing to know about how Perl passes arguments into functions is that arguments are passed by reference, not by value. This is illustrated in the following example:

#!/usr/bin/perl -w
# byref1.pl

use strict;

my $var = 10;
print “before: $varn”;
change_var($var);
print “after: $varn”;

sub change_var {
print “in change_var() before: $_[0]n”;
++$_[0];
print “in change_var() after: $_[0]n”;
}

First, $var is assigned 10 and then printed. Then, $var is passed into the function change_var() . This function prints the value of $_[0] , increments it, then prints it again. The important line of code in this function is

++$_[0];

Since the arguments to the function are passed in through the array @_ , to access the zeroth argument of the array we use the syntax $_[0] —this function prints it, increments it, then prints it again. The important thing to note about this code is that since $var is passed into the function by reference, when $_[0] is incremented, Perl actually increments the argument passed in, $var , from 10 to 11. After the function call, the program then prints the resulting value of $var , which is now 11. Executing the code proves this:

$ perl byref1.pl
before: 10
in change_var() before: 10
in change_var() after: 11
after: 11
$

The fact that Perl passes arguments by reference is not in itself a bad thing, but it can be if you are not expecting it. Having functions modify arguments when we don’t want them to can create hard-to-find bugs. There is a very simple way to ensure that our functions don’t modify their arguments—simply copy them into my() variables as shown in this example:

#!/usr/bin/perl -w
# byref2.pl

use strict;

my $var = 10;
print “before: $varn”;
change_var($var);
print “after: $varn”;
sub change_var {
my($v) = @_;
# or: my $v = shift;

print “in change_var() before: $vn”;
++$v;
print “in change_var() after: $vn”;
}

The big change here is the first line of change_var() :

my($v) = @_;

This copies the zeroth element of @_ , or $_[0] , into $v . As mentioned before and as indicated by the comment, we could have written this as

my $v = shift;

since the shift() function shifts @_ by default if invoked within a function (recall also that if shift() is invoked outside a function it shifts @ARGV by default). Now, since the argument is copied into $v , when we increment it with

++$v;

it increments the copy within the function; it does not increment $var . Executing the program proves this:

$ perl byref2.pl
before: 10
in change_var() before: 10
in change_var() after: 11
after: 10
$

Please check back for the conclusion to this article series.
[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye