Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What scope is an undeclared variable used deep in code?

Tags:

scope

perl

# my @arr;   
for (1..100)
{
    for (1..100)
    {
        for (1..100)
        {
            push @arr, 1;
        }
    }
}

What is the scope of @arr? Is it the same as if it was declared in the commented line at the top?

like image 511
CJ7 Avatar asked Feb 06 '23 02:02

CJ7


1 Answers

The @arr is a global variable, created when it is first encountered by the parser, and then seen in the whole package.

use warnings;
#use strict;

for (1..3) {
    #my @arr;
    for ( qw(a b c) ) {
        push @arr, $_;
    }   
}

print "@arr\n";

It prints

a b c a b c a b c

This is one of the bad things about globals, that they "radiate" throughout the code.

With use strict; enabled we get

Possible unintended interpolation of @arr in string at scope.pl line 11.
Global symbol "@arr" requires explicit package name at scope.pl line 7.
Global symbol "@arr" requires explicit package name at scope.pl line 11.
Execution of scope.pl aborted due to compilation errors.

Since strict merely enforces declarations, this meaningfully informs us that @arr is global (thus seen everywhere in the code).

Declaring it with my at the top would have the same effect in this example, but it is not the same thing as an undeclared, global variable. A my variable is lexical and has scope, the nearest enclosing block (or file, here). From my

A my declares the listed variables to be local (lexically) to the enclosing block, file, or eval. If more than one variable is listed, the list must be placed in parentheses.

Also, lexicals are not in the symbol table.

So when it is declared inside the first loop (commented out line) then the following push @arr... refers to that variable, which does not exist outside of that loop's block (and so is not seen at the end). The last line then refers to another variable, a global @arr created right there, which was never assigned to. We do get the warning

Possible unintended interpolation of @arr in string at scope.pl line 11.
Name "main::arr" used only once: possible typo at scope.pl line 11.

about empty main::arr used once, and an empty line since it is printed.

See also Private variables via my() in perlsub


At compile time, when it is first seen by the parser

like image 150
zdim Avatar answered Mar 07 '23 08:03

zdim