A couple of points.

"unless the other subroutine is defined within the sub containing the my scoped valiable" - don't define named subroutines within named subroutines! Ever!

sub outer { ... sub inner { } ... }

This is never a good idea. First, the inner() subroutine will not be local to the outer() one, it will still be globally accessible. Second, if you use a lexical variable (variable declared with my) defined in outer() within inner() you will get the "Variable will not stay shared" warning and strange things will happed in runtime. The thing is that each invocation of the outer() creates a new instance of the lexical variable, but the inner() may be called directly or recursively or ... so there is no good way to tie the $x in inner() to a specific instance in outer().

If you want a subroutine to change a lexical declared in another, pass a reference or make use the fact that $_[...] is an alias to the parameter. If you want to have a shared state for two subroutines, use this:

{ my $hidden_data; sub one { ... access the $hidden_data; ... } sub two { ... access the $hidden_data; ... } }

It's legal though to use a lexical variable in an unnamed subroutine defined within a subroutine like this:

sub outer { my $lexical = ...; ... my $inner = sub { ...; access $lexical; ... }; ... $inner->(...); #or even return $inner; }

In this case the $inner subroutine is lexical and defined in the same or smaller scope as the $lexical so there is no confusion regarding which instance of $lexical should it be accessing. And if you return or store the $inner, the value of $lexical will be preserved and will not be garbage collected until all references to the unnamed subroutine are cleared.

local is in no way similar. First and foremost, local doesn't declare a new variable. It takes a "slot" (it may be global variable or array or hash element, but not a lexical variable), stacks its value away and undefines the slot. Then when the execution leaves the enclosing block, the old value is reassigned to the slot.

Apart from other things this means that

my $hash{key} = ...; # is illegal local $hash{$key} = ...; # is legal #on the other hand my $x = 1; { my $x = 2; # is legal, a new variable was created, outer $x is not v +isible } #while my $x = 1; { local $x = 2; # is illegal. Can't localize a lexical variable

"If the variable is defined in the same block as the subroutines then my and local are effectively the same" - INCORRECT! Try this:

our $variable = 15; { local $variable = 33; sub one { print "in one(): \$variable = $variable\n"; } sub two { print "in two(): \$variable = $variable\n"; } } one(); two(); $variable = 99; one(); two();
versus
our $variable = 15; { my $variable = 33; sub one { print "in one(): \$variable = $variable\n"; } sub two { print "in two(): \$variable = $variable\n"; } } one(); two(); $variable = 99; one(); two();

In the first example the $variable (the only $variable in the whole script! A global variable!) is only ever set to 33 while defining the two subroutines, but not when you call them.

In the second there are two variables called $variable. A global one assigned on line 1 and 16 and a lexical one declared at line 4 and accessed at lines 6 and 9. The lexical variable is visible only within the enclosing block but stays alive for the whole runtime of the script, the RUNTIME effects of local only lasted for a tiny moment before any of the subroutines were called.

Read also Coping with Scoping

Jenda
Enoch was right!
Enjoy the last years of Rome.


In reply to Re^5: Is use strict always appropriate? by Jenda
in thread Please help me print this hash. by Je55eah

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.