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

I am currently cleaning up some old code - among other things to comply with the strict pragma - and need to know the semantics of assigning/declaring package variables. Given the simple example
package P; $A = 'something';
then strict complains about $A missing an explicit package name. That's ok, it's what strict is supposed to do. In an effort to understand and decide on the best way to fix this, I tried the following short program:
package main; my $A = 123; $::A = 456; print ('package '.__PACKAGE__."\n"); print ('$A is '.$A."\n"); print ('our $A is '.our $A."\n"); print ('$::A is '.$::A."\n"); print ('$main::A is '.$main::A."\n"); print ('$main\'A is '.$main'A."\n");
which generates the following output:
package main $A is 123 our $A is 456 $::A is 456 $main::A is 456 $main'A is 456
It's the 2nd line that caught my attention. Apparently, $A (declared globally) and $::A are not the same variable. Is this correct? I seem to have missed that in the Perl documentation. And exactly what happens during the assignment (without declaration) in the first example? Does the reference to $A get converted to $P::A because of the package statement, resulting in that variable being created during the assignment?

Discussion eqilogue - added after a couple of days

Thank you all for eventually guiding me towards the right track. The reference to the tutorial "Coping with Scoping" was especially useful. This tutorial is very precise and informative. Please bear in mind that my question was about (old) non-strict code - not best practice for the future. At least with non-strict code, the difference between a lexical alias and what used to be called a "package variable" can matter a great deal.

Replies are listed 'Best First'.
Re: how to declare a package variable
by AnomalousMonk (Archbishop) on Apr 15, 2016 at 02:15 UTC

    Certainly read the tutorials linked by AnonyMonk above.

    Then consider the following code:

    c:\@Work\Perl\monks>perl -le "use warnings; use strict; ;; package P; ;; $P::A = 'something'; ;; package main; ;; my $A = 123; $::A = 456; ;; print 'package ', __PACKAGE__; print qq{\$A is $A}; print qq{\$::A is $::A}; print qq{\$main::A is $main::A}; print qq{\$P::A is $P::A}; print qq{\n}; ;; our $A; print 'package ', __PACKAGE__; print qq{\$A is $A}; print qq{\$::A is $::A}; print qq{\$main::A is $main::A}; print qq{\$P::A is $P::A}; " "our" variable $A masks earlier declaration in same scope at -e line 1 +. package main $A is 123 $::A is 456 $main::A is 456 $P::A is something package main $A is 456 $::A is 456 $main::A is 456 $P::A is something
    In this code:
    1. The package (or namespace) P is declared and the package variable $P::A is defined and initialized in it. This variable is autovivified by the assignment operation. strict is happy with this assignment because the package variable name is fully qualified.
    2. The package (or namespace) is switched to main and a lexical variable $A is defined and initilized, and a package variable $main::A in the main namespace is defined and initialized. (The shorthand form of the fully qualified name $main::A is used.) The lexical variable is "visible" until the end of its lexical scope: the end of the program in this case although it might have been given a much narrower scope. The package variable is visible from any scope and any module; it is truly global.
    3. The set of print statements shows that the lexical variable $A and the package variable $main::A (or $::A) are independently accessible.
    4. The  our $A; statement is executed. our creates a lexical alias of the $A symbol to the package variable $main::A for the remainder of the lexical scope. I have taken this expression out of the print statement and made it a separate statement to more clearly illustrate how it works. The alias of the symbol $A to $main::A means that the original lexical variable (the my variable) named $A is no longer "visible", i.e., accessible. That's what the warning is about.
    5. Another set of print statements identical to the first illustrates that $A is now indeed the same as $::A and $main::A.
    6. In all the print statements, the $P::A variable is always fully accessible because it is always fully qualified.


    Give a man a fish:  <%-{-{-{-<

      Thank you for the explanations. There is just one more thing: Are the semantics of
      package P; $A = 'something';
      better matched by
      package P; $P::A = 'something';
      or by
      package P; our $A = 'something';
      or do they all differ from one another?

        This package P; our $a = 'something'; is equivalent to package P; $P::a = 'something';.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.

        BrowserUk has already answered this question pretty clearly here and here. I just want to re-emphasize that all three statements you give as examples above do the same thing: they create (if the variable didn't already exist) and assign to a global variable $A in the P package (or namespace), with the our statement further granting lexical visibility.

        The  $A = 'something'; statement is made illegal (due to all the foot injuries) by enabling strictures; see strict.


        Give a man a fish:  <%-{-{-{-<

Re: how to declare a package variable
by Marshall (Canon) on Apr 15, 2016 at 00:27 UTC
    A "my" variable has lexical scope. There could be a bunch of "my" variables of the same name (eg my $couter;) within a script, each referencing a different distinct variable depending upon the scope. No "my" variable can be referenced by another module.

    An "our" variable goes into the module's symbol table is essentially global - there can be only one. These are seen only rarely.

    I am not sure what happens in ancient code like this. I suppose that there could be the idea of a global that is not in the symbol table? In that case these are "different" variables, one limited globally to the package and one that can be referenced by other packages. A "my variable" declared in the right scope is also "global" to the compilation unit. But an "our" variable can be visible to other separately compiled modules.

Re: how to declare a package variable
by Anonymous Monk on Apr 15, 2016 at 00:32 UTC

    ....

    "globally" means in current package (main by default)

    $::foo is shorthand for $main::foo

    So you have two globals ($P::A/$main::A) and a lexical ($A)

    If you use warnings you'll get a warning about "my $A" being made invisible by "our $A" ( "our" variable $A masks earlier declaration in same scope )

    Tutorials: Variables and Scoping: Coping with Scoping, Lexical scoping like a fox