4

Previously I read related content in the book of "Effective Perl Programming", but didn't really understand it. Today, I encountered a problem about this, as below code.

my $vname = "a";
my @a = qw(1 2 3);
local @array = @$vname; 
foreach(@array) { print "$_\n"; };

It output nothing. Then I modified this line:

local @a = qw(1 2 3);  

Just replaced "my" with "local", then it works now. So I'd like to figure out what's the difference between them.

serenesat
  • 4,611
  • 10
  • 37
  • 53
thinkhy
  • 923
  • 13
  • 25
  • Try [perldoc here](http://perldoc.perl.org/functions/local.html) – the wolf Aug 30 '12 at 04:28
  • 1
    Thanks, but I don't think the perldoc shows the essential difference from the compiler's perspective. Maybe I have to reread Perl book tonight. – thinkhy Aug 30 '12 at 04:32
  • Duplicate: http://stackoverflow.com/questions/3603466/how-is-my-faster-than-local-in-perl and http://stackoverflow.com/questions/129607/what-is-the-difference-between-my-and-local-in-perl – clt60 Aug 30 '12 at 15:04

5 Answers5

14

There is a perldoc entry which answers this question in perlfaq7:

What's the difference between dynamic and lexical (static) scoping? Between local() and my()?

local($x) saves away the old value of the global variable $x and assigns a new value for the duration of the subroutine which is visible in other functions called from that subroutine. This is done at run-time, so is called dynamic scoping. local() always affects global variables, also called package variables or dynamic variables. my($x) creates a new variable that is only visible in the current subroutine. This is done at compile-time, so it is called lexical or static scoping. my() always affects private variables, also called lexical variables or (improperly) static(ly scoped) variables.

For instance:

sub visible {
    print "var has value $var\n";
}

sub dynamic {
    local $var = 'local';   # new temporary value for the still-global
    visible();              #   variable called $var
}

sub lexical {
    my $var = 'private';    # new private variable, $var
    visible();              # (invisible outside of sub scope)
}

$var = 'global';
visible();              # prints global
dynamic();              # prints local
lexical();              # prints global

Notice how at no point does the value "private" get printed. That's because $var only has that value within the block of the lexical() function, and it is hidden from the called subroutine.

In summary, local() doesn't make what you think of as private, local variables. It gives a global variable a temporary value. my() is what you're looking for if you want private variables.

See Private Variables via my() in perlsub and Temporary Values via local() in perlsub for excruciating details.

Zaid
  • 36,680
  • 16
  • 86
  • 155
9

my creates a new variable. It can only be seen in the lexical scope in which it is declared.

local creates a temporary backup of a global variable that's restored on scope exit, but does not reduce its scope (it can still be seen globally). It does not create a new variable.

You always want to use my when possible, but local is a decent approximation when you have to deal with global variables (e.g. $_).

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 3
    `local` also works on hash and array elements, so it's useful for temporarily changing those too. – ikegami Aug 30 '12 at 04:53
8

There are two kinds of variable scopes in Perl:

  • Global variables: They reside in the current package, can be accessed from the outside and can have "local" values. The name can be used as a key in the "stash", the package variable hash / the symbol table.
  • Lexical variables: They reside in the current scope (roughly delimited by curly braces). There is no symbol table that can be inspected.

Lexical variables and global variables do not interfere, there can be two different variables with the same name.

Most Perl variable magic happens with global variables. The following syntax works with global variables:

our $var;
$::var;
$main::var;
${'var'};
local $var;

but not my $var.

So we can write:

@::array = qw(a b c);
my @secondArray = @{array};

Which copies the arrays. We can also look up the array with a name that is stored in a variable:

@::array = qw(a b c);
my $name = "array";
my @secondArray = @{$name};

The last line abbreviates to … = @$name.

This is not possible with lexical vars because they do not reside in the stash.

The local function assigns a "local" value to a global variable (and globals only) within the current scope and in the scope of all subs that are called from within this scope ("dynamic scope").

Originally (in Perl 4) meddling with variable names and the stash was the only way to simulate references. These usages are now mostly outdated by ~2 decades as references are available (what is far safer).

ikegami
  • 367,544
  • 15
  • 269
  • 518
amon
  • 57,091
  • 2
  • 89
  • 149
  • 2
    The key part of your post is wrong. `local $var` is not even close equivalent to any of the others. `local $var` is the only one that changes `$var`. (`local our $var`, `local $::var`, `local $main::var`, ... would be the roughly equivalent versions.) – ikegami Aug 30 '12 at 04:56
  • This is called a "soft reference", and is one of the things that `strict` keeps you from doing. – brian d foy Aug 30 '12 at 13:43
2

I would like to focus on the main cases when you would use them :

  • my should be your "default" for variables that you wish to keep restricted to a specific block. This should be most of the time
  • local is useful if you wish to use a global variable, particular one of the special variables. For example

    local $/;                          # enable "slurp" mode
    local $_ = <$some_file_handle>;    # whole file now here
    

    Using local prevents your change from affecting other code (including modules you didnt write)

justintime
  • 3,601
  • 4
  • 22
  • 37
0

In your case, the difference is that local addressed a variable in the symbol table and my does not. This is important because of how to use it:

local @array = @$vname;

That is, you're using $vname as a symbolic reference (a questionable practice absent no strict 'refs' to tell us you know what you're doing). Quotha:

Only package variables (globals, even if localized) are visible to symbolic references. Lexical variables (declared with my()) aren't in a symbol table, and thus are invisible to this mechanism.

So symbolic references can only refer to variables in the symbol table. Whether you declare @a as lexical with my or as global with local, @$vname only ever refers to @main::a. When you say

local @a = qw(1 2 3);

, you are giving a new value to @main::a. When you say

my @a = qw(1 2 3);

, you are creating a new lexical variable @a and giving it a value, but leaving @main::a undefined. When

local @array = @$vname;

then accesses the value of @main::a, if finds it to be undefined and sets the value of @array to it.

If all that seems confusing, that's because it is. This is why you are strongly encouraged to use strict and warnings (which would have exploded prettily on this code) and discouraged from using symbolic references unless you really know what you're doing.

darch
  • 4,200
  • 1
  • 20
  • 23