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

use strict; use warnings; use Data::Dumper; our $VAR=5.0; sub printit{print "Package Main VAR=$VAR\n";} package A; our $VAR=2.0; sub printit{print "Package A VAR=$VAR\n";} package B; our $VAR=3.0; sub printit{print "Package B VAR=$VAR\n";} package C; our $VAR=4.0; sub printit{print "Package C VAR=$VAR\n";} package main; A::printit; B::printit; C::printit; printit; print "Package Main VAR=$VAR\n";
Output of the above script it.... Package A VAR=2 Package B VAR=3 Package C VAR=4 Package Main VAR=5 Package Main VAR=4

COMMENT : I am confused to see the result. As per my understanding, the last line of the result should be same as second last line. Please help. Thank you.

Regards, Santosh Prasad

Replies are listed 'Best First'.
Re: package variable scope ('our' has lexical scope)
by LanX (Saint) on Jun 14, 2015 at 12:30 UTC
    Our is (like my ) lexically scoped, your last print puts the last $VAR.

    you should have called main::printit()

    Think of our as an aliasing mechanism, qualifying a $var as $__PACKAGE__::var for the rest of the scope, but taking the package at declaration time!

    To be able to limit the scope use {curlies}.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

    update

    And is very clearly documented:

    An our declaration declares an alias for a package variable that will be visible across its entire lexical scope, even across package boundaries. The package in which the variable is entered is determined at the point of the declaration, not at the point of use. This means the following behavior holds:

    package Foo; our $bar; # declares $Foo::bar for rest of lexical scope $bar = 20; package Bar; print $bar; # prints 20, as it refers to $Foo::bar

Re: package variable scope
by AnomalousMonk (Archbishop) on Jun 14, 2015 at 16:17 UTC

    Further to LanX's reply: In addition to using  { } curlies to limit/select scope, one can fully qualify package names:

    c:\@Work\Perl\monks>perl -wMstrict -le "our $VAR = 5.0; sub printit { print 'Package ', __PACKAGE__, qq{ VAR=$VAR}; } ;; package A; our $VAR = 2.0; sub printit { print 'Package ', __PACKAGE__, qq{ VAR=$VAR}; } ;; package main; ;; A::printit; printit; main::printit; print 'Package ', __PACKAGE__, qq{ unqualified VAR=$VAR}; print 'Package ', __PACKAGE__, qq{ fully qualified VAR=$main::VAR}; " Package A VAR=2 Package main VAR=5 Package main VAR=5 Package main unqualified VAR=2 Package main fully qualified VAR=5


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

Re: package variable scope
by shmem (Chancellor) on Jun 14, 2015 at 17:49 UTC

    Your last statement uses $VAR unqualified, so it is the last $VAR of whatsoever package that has been allocated - which happens to be the incarnation of $VAR in package C.
    Consider:

    use strict; use warnings; our $VAR=5.0; sub printit{print "Package Main VAR=$VAR\n";} package A; our $VAR=2.0; sub printit{print "Package A VAR=$VAR\n";} package B; our $VAR=3.0; sub printit{print "Package B VAR=$VAR\n";} package C; our $VAR=4.0; sub printit{print "Package C VAR=$VAR\n";} package main; $VAR="foo"; A::printit; B::printit; C::printit; printit; print "Package Main VAR=$VAR\n"; print <<EOH; A: $A::VAR B: $B::VAR C: $C::VAR main: $main::VAR whatever: $VAR EOH __END__ Package A VAR=2 Package B VAR=3 Package C VAR=foo Package Main VAR=5 Package Main VAR=foo A: 2 B: 3 C: foo main: 5 whatever: foo

    Declaring a variable as our creates a lexically scoped variable spanning packages, which will create a symbol table slot in the current package in which the our declaration ocurred. This lexical variable will be bound to the symbol table of that package until re-declared (think bless) into another package. Altering the unqualified alias results in altering the value in the symbol table slot of that last package. That is why you get foo for $C::VAR above: $VAR - unqualified - is still bound to package C when it is last modified in package main.

    If you remove the our declaration after package B, then $VAR will yield 3 for both package A and B.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'