Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I'm having a bit of trouble with using some local scope variables. I have a function where I want to define a variable, then use that variable in a sub function. That sounds like the text book definition for when to use a local scope variable. Below is the test script that I'm using.

I'm using the 'use strict' declaration as all the books I've read (O'Reilly's) say that's a Good Thing to do.

Can someone offer some insight as to why when I declare $a it's ok, but declaring $aa gives me an error?

I'm using Active State's Perl v5.8.3 build 809 for Windows.

Thanks for any help

- Josh

use strict; test1(); sub test1 { local $a = 1; local $aa = 2; test2(); } sub test2 { print "a = $a\n"; print "aa = $aa\n"; } # Global symbol "$aa" requires explicit package name at C:\projects\Tr +acing\test.pl line 8. # Global symbol "$aa" requires explicit package name at C:\projects\Tr +acing\test.pl line 15. # Execution of C:\projects\Tracing\test.pl aborted due to compilation +errors.

Replies are listed 'Best First'.
Re: Local Scope Variables
by bart (Canon) on Feb 13, 2004 at 01:47 UTC
    Your mistake: local does not declare a variable.

    All it does is, at runtime, temporarily save the value of the global variable, and clear it; and restore it to its old value when the scope is left.

    Taking into account that the global variables $a and $b have a special status with regard to strict, because of their connection to sort, and these therefore don't need a declaration, it should be clear to you by now that strict simply complains because you haven't actually declared $aa.

    For that purpose, use

    use vars qw($aa);
    or our, as in
    our $aa;
    to declare it as a global variable; or in a similar way, use my to make it a lexical variable:
    my $aa;
    n.b. If you want to declare multiple variables at once with our or my, put the comma separated list between parentheses. For use vars, put the names in qw(...) next to each other separated with whitespace — not commas.

    Note that in general it's a big mistake to make $a or $b a lexical variable, because that would mess up their use with sort really good.

    For more on the difference between lexical variables and global variables, see perlfaq7: What's the difference between dynamic and lexical (static) scoping? Between local() and my()?

Re: Local Scope Variables
by borisz (Canon) on Feb 12, 2004 at 23:42 UTC
    some vars are already defined $a is one of them. From the perlvar
    $a $b Special package variables when using sort(), see "sort" in perlfunc. Because of this specialness $a and $b don't need to be declared (using use vars, or our()) even when using the "strict 'vars'" pragma. Don't lexicalize them with "my $a" or "my $b" if you want to be able to use them in the sort() comparison block or function.
    Boris
Re: Local Scope Variables
by revdiablo (Prior) on Feb 13, 2004 at 08:32 UTC

    I'm surprised nobody has yet posted a link to MJD's excellent Coping with Scoping article. You should give it a read sometime.

      While the article is excellent, the question has already been answered :)
        the question has already been answered

        <rhetorical>So additional information is not wanted?</rhetorical>

        My experience at the Monastery says otherwise. I occasionally post "useless" responses like this when I think it could benefit people in the future. Someone finding this thread via supersearch would probably do well to read Coping with Scoping, so that's why I posted a link to it.

Re: Local Scope Variables
by davido (Cardinal) on Feb 13, 2004 at 02:26 UTC

    One thing that I would like to add is the fact that it's generally a bad idea to allow functions or subs to absorb variables of greater scope by osmosis. If you want test2() to have access to a variable created in test1(), pass it to test2() by reference. If you want test2() to just receive the value, pass by value (instead of reference). But if you can at all avoid it, don't pass implicitly by assuming globals will be there to leak into functions.

    There are exceptions, and one exception I can think of is static variables... this for example:

    { my $static = 10; sub test1 { print $static++, "\n"; } } test1(); test1(); __OUTPUT__ 10 11

    This is a special situation where you actually want to access variables from outside of the sub's internal scope.


    Dave

Re: Local Scope Variables
by PodMaster (Abbot) on Feb 12, 2004 at 23:38 UTC
Re: Local Scope Variables
by hhdave (Beadle) on Feb 12, 2004 at 23:51 UTC

    This is really, really bizarre. I'm using 5.8.1-RC3 in MacOS X 10.3. Here is what I've found:-

    If I comment out the lines of test2, then change local $aa =... to local $b = I get no errors. If I change the '$a' assignment to something with 2 letters then I get another error due to that line. I seems as though perl only generates the global symbol error for variables with more than one letter in their name. Very strange.

    The obvious way to fix the problem is to do what the error messages are asking for - give a global package name by putting $main::aa

    This is not a very good idea though. In general you would be better to pass parameters into the function, and use return values from a function to achieve what you want. Only use global variables as an absolute last resort. (I've never used the 'local' decleration by the way!)

    use strict; test1(); sub test1 { test2(1,2); } sub test2 { my ($a, $aa) = @_; print "a = $a\n"; print "aa = $aa\n"; }
      hhdave, see borisz's response above yours. Basically, $a and $b are on the short list of special variables that are automatically declared by perl, so they already exist in any scope.

      As of perl 5.6, you should probably just use my instead of local anyway, but use a variable with meaning to you, not a special one like $a or $b. . .

Re: Local Scope Variables
by mce (Curate) on Feb 13, 2004 at 08:10 UTC