Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

The difference between my and local

by cLive ;-) (Prior)
on Jul 05, 2001 at 08:12 UTC ( [id://94007]=perltutorial: print w/replies, xml ) Need Help??

Well, this confused the hell out of me, so I thought I'd spend some time getting my head around it.

Probably best to show by example (apologies to Joseph Hall and merlyn for borrowing heavily here from Effective Perl Programming)

Quick summary: 'my' creates a new variable, 'local' temporarily amends the value of a variable

There is a subtle difference.

In the example below, $::a refers to $a in the 'global' namespace.

$a = 3.14159; { local $a = 3; print "In block, \$a = $a\n"; print "In block, \$::a = $::a\n"; } print "Outside block, \$a = $a\n"; print "Outside block, \$::a = $::a\n"; # This outputs In block, $a = 3 In block, $::a = 3 Outside block, $a = 3.14159 Outside block, $::a = 3.14159

ie, 'local' temporarily changes the value of the variable, but only within the scope it exists in.

so how does that differ from 'my'? 'my' creates a variable that does not appear in the symbol table, and does not exist outside of the scope that it appears in. So using similar code:

$a = 3.14159; { my $a = 3; print "In block, \$a = $a\n"; print "In block, \$::a = $::a\n"; } print "Outside block, \$a = $a\n"; print "Outside block, \$::a = $::a\n"; # This outputs In block, $a = 3 In block, $::a = 3.14159 Outside block, $a = 3.14159 Outside block, $::a = 3.14159

ie, 'my' has no effect on the global $a, even inside the block.

But in real life, they work virtually the same?

Yes. Sort of. So when should you use them?

  • use 'my' when you can (it's faster than local)
  • use local when:
    • you're amending code written in Perl 4, unless you are sure that changing 'local' to 'my' will not cause any lexical problems
    • you want to amend a special Perl variable, eg $/ when reading in a file. my $/; throws a compile-time error

If you use Perl 5 and strict (and I know you do :), you probably haven't noticed any difference between using 'my' and 'local', but will hopefully only use 'local' in the second instance above.

EPP also suggests you use 'local' when messing with variables in another module's namespace, but I can't think of a RL situation where that could be justified - why not just scope a local variable? Perhaps someone could enlighten me?

But, if you ever end up amending some old Perl 4 code that uses local, you need to be aware of the issues and not just do a s/\blocal\b/my/gs on the script :) - sometimes people use the 'features' of local in unusual ways...

Hope that's cleared a few things up.

cLive ;-)

Replies are listed 'Best First'.
my/local, space/time (was: Re: The difference between my and local)
by ariels (Curate) on Jul 05, 2001 at 11:16 UTC
    "'local' temporarily changes the value of the variable, but only within the scope it exists in."
    What does it mean? What's this "scope" they keep telling you about?

    Here's a nice way to distinguish my from local.

    • my works in space: the program sees that variable (by that name) throughout the static scope. That scope is simply delimited from the point of the `my' to the end of the block. If I say
      { # ... my ($x, @y, %z); # (1) # ... sub foo { # ... } # ... foo(17); # (2) bar($x,29); # (3) # ... } # (4) # ... sub bar { # ... }
      then %z,@y,$x are the temporary ones from declaration (point (1)) to the end of the block (point (4)). In particular, the call to foo (point (2)) can see all three variables, because foo was defined within the scope. The call to bar (point (3)) can't see @y,%z, because bar is defined outside the block's scope. Of course, that particular call can see $x as a parameter.

      Note how easy it is to tell the scope of a `my' declaration: it's a lexical thing. All you have to do is look for the end of the block (point (4)). The `my' variable is visible from its declaration to the end of the block, and nowhere else.

    • local works in time: the program sees that version of the (global) variable in the dynamic "scope". The version of the variable is used from the moment (at run time) where the `local' declaration is encountered, to the moment (again at run time) where the block ends. It doesn't matter where your code is defined, it gets to see that version of the variable if it gets to run between these two times. That's why `local' variables are versions of global variables: they potentially have to be seen by all routines in the program. If I say
      use vars qw/$x, @y, %z/; { # ... local ($x, @y, %z); # (5) # ... sub baz { # ... } # ... baz(17); # (6) quux($x,29); # (7) # ... } # (8) # ... sub quux { # ... } # ... baz(29); # (9)
      then the global variables $x,@y,%z (declared in the use vars pragma) are given temporary versions at point (5). These temporary versions are in effect until execution reaches the end of the block (point (8)), at which time the old versions come back.

      It doesn't matter that baz is defined inside the block. The call at point (6) uses the temporary versions, because it happens (in time!) between (5) and (8); the call at point (9) uses the original versions, because it happens (in time!) after (8). The call to quux can see the temporary versions of all 3 variables, even though the definition of quux occurs outside the variable. What matters is that the call occurs during the temporary scope.

Re: The difference between my and local
by davorg (Chancellor) on Jul 05, 2001 at 14:05 UTC

    In my experience you can only really explain the difference between my and local once you've explained the difference between package and lexical variables.

    A package variable is associated with a package (hence the name!) It lives in the package's symbol table and can be accessed from anywhere within the package. A package variable can also be qualified with its package name (e.g. $my_package::variable) and, in this form, can be accessed from anywhere in the program.

    A lexical variable is associated with a block of code. It lives in a pad and can only be accessed from within the block.

    local only works with package variables. It stores the existing value of the variable and gives it a new, undef, value. The previous value of the variable is restored when the innermost enclosing block of code is exited.

    my creates a new lexical variable. The variable only exists until the innermost enclosing block of code is exited.

    --
    <http://www.dave.org.uk>

    Perl Training in the UK <http://www.iterative-software.com>

Re: The difference between my and local
by Hofmator (Curate) on Jul 05, 2001 at 15:43 UTC
Re: The difference between my and local
by bart (Canon) on Jun 08, 2007 at 11:21 UTC
    EPP also suggests you use 'local' when messing with variables in another module's namespace, but I can't think of a RL situation where that could be justified - why not just scope a local variable? Perhaps someone could enlighten me?
    Well, an example.
    %hash = ( one => "a\tb", two => chr(7) ); { use Data::Dumper; local $Data::Dumper::Useqq = 1; local $Data::Dumper::Terse = 1; print Dumper \%hash; }

    This way you temporarily replace the value of settings, while perl resets them back to their original state afterwards.

Re: The difference between my and local
by nashr (Novice) on Dec 20, 2004 at 18:47 UTC
    This brings me to the problem I've been having. I have a "my" variable that I want to update within an if..elsif, but it does not get updated.
    my $a = "TEST'; if ($x == 1) { $a = "one"; } elsif ($x == 2) { $a = "TWO"; } else { $a = "EMPTY"; }
    However, $a is not getting updated. I'm obviously overlooking something in either declaring the variable to be global, or some way to reference the variable directly. I just don't quite know where to look. Anyone???

      That code doesn't compile. TEST starts with double quotes and ends with a single quote. If I fix that, this works as expected for me. Here's a version you can run with your $x argument given on the command line:

      use strict; my $x = shift(@ARGV); my $a = "TEST"; if ($x == 1) { $a = "one"; } elsif ($x == 2) { $a = "TWO"; } else { $a = "EMPTY"; } print "a=$a\n";

        I am getting following error, when I use strict and use $tt instead of $a My Code:-
        use strict; my $tt = 3.14159; { local $tt = 3; print "In block, \$tt = $tt\n"; print "In block, \$::tt = $::tt\n"; } print "Outside block, \$tt = $tt\n"; print "Outside block, \$::tt = $::tt\n";
        My Error:-
        Can't localize lexical variable $tt at basic.pl line 4.
      The first line contains an error. TEST is enclosed in a double and a single quotation mark.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perltutorial [id://94007]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2024-03-19 08:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found