http://qs321.pair.com?node_id=574467

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

what is the purpose of this declaration?

IF you had multiple packages in one file;
then this would be useful for a file-global variable (the lexical scope)

but what other function does it fulfill?

what does it mean that it does not CREATE a local variable?
is the namespace reserved in the symbol table, but no memory has been allocated for it?
isn't that what my does?
my $var; isn't both a symbol table entry created and memory allocated? our $var; only a symbol table entry?

also it's wierd that you can declare a variable OUR as well as MY
package packA; use strict; our $ourVAR; $ourVAR = "123 ABC"; print " packA ourVAR = $ourVAR \n"; my $ourVAR = "456 RST"; print " packAA ourVAR = $ourVAR \n";

and sure enough, ourVAR gets the new value.
so what am i missing? :-)

Replies are listed 'Best First'.
Re: OUR declaration
by davido (Cardinal) on Sep 23, 2006 at 04:21 UTC

    my $var; doesn't do anything to the symbol table. It creates a lexical variable in a sort of lexical pad. A lexical variable is created, lexically scoped, and completely independent of the package symbol table.

    our $var; creates an entry in the symbol table. our does create an entry in the symbol table. our follows scoping rules similar to my, but the variable created is a package global.

    Try this:

    package main; use strict; use warnings; my $lexical = 100; our $global = 200; print $main::global, "\n"; print $main::lexical, "\n";

    The output shows that "my $lexical" never created an entry in the global symbol table.

    It's not wierd that you can declare an our variable and a my variable at the same time, because they're two different variables. It's true that one can mask the other if you're not using "fully qualified" names. But nevertheless, the two variables to exist.

    Try the following example where two variables by the same name are created:

    package main; use strict; use warnings; our $var = 200; my $var = 100; print $var, "\n"; print $main::var, "\n";

    Now it will print 100 then 200 (and some warnings). This shows that even though the my declaration "masks" the our declaration, you can still get at the global by using its fully qualified name. If you had declared the lexical first and then the 'our' variable, the lexical becomes masked, and since there's no such thing as a "fully qualified" lexical name, you can't get at it anymore, until the 'our' variable passes out of scope (which in the case of my example isn't possible, but it is possible to construct such a situation pretty easily).

    References also help to illustrate what's going on. Watch this:

    package main; use strict; use warnings; my $var = 100; my $ref_to_lexical = \$var; our $var = 200; my $ref_to_global = \$var; print $var, "\n"; # This prints 200. The lexical is masked. print $$ref_to_global, "\n"; # This prints 200. print $$ref_to_lexical, "\n" # This prints 100, it refers to # the lexical $var.

    Clear as mud? :)


    Dave

Re: OUR declaration
by tilly (Archbishop) on Sep 23, 2006 at 02:25 UTC
    To the best of my knowledge, it is a placeholder for things that are being thought about in Perl 6. The only convenience in Perl 5 is that it provides a way to cut out a use vars declaration for common globals (eg @ISA, $VERSION and @EXPORT_OK).

    For more thoughts on why it is bad, see Why is 'our' good?. TimToady's response gives an idea why it might prove more useful in Perl 6.


      thanks. that was an excellent article.
      let me ask a follow-up question

      for the "normal" scenario of one file == one package;
      is there ever a case where our (instead of my) is needed?

        Needed? You need a global variable if you are going to set one with special meaning to Perl, or to an external module. But even then you don't need our to set those globals. (The most common globals that people do this with are @ISA, $VERSION, @EXPORT and @EXPORT_OK.)

        For instance a lot of people tend to write:

        package Foo; use strict; our @ISA = 'Bar'; ...
        instead of
        package Foo; use strict; use vars qw(ISA); @ISA = 'Bar'; ...
        so you can save a line. However you can solve that problem in other ways, for instance:
        package Foo; @ISA = 'Bar'; use strict; ...
        or
        package Foo; use strict; @Foo::ISA = 'Bar'; ...
        or in this case
        package Foo; use strict; use base 'Bar'; ...
        So our is always pretty gratuitous.
        If you want a global variable, i.e. one that can be read from other packages and does not go out of scope, then you either spell the whole thing out ($SomePackage::Variable) or use our so you can say ($Variable) within that file.
Re: OUR declaration
by ikegami (Patriarch) on Sep 23, 2006 at 03:35 UTC

    what does it mean that it does not CREATE a local variable?

    That's mostly true. Consider these three programs:

    $var = "value"; print($main::var eq "value" ? "true" : "false", "\n"); # true
    our $var = "value"; print($main::var eq "value" ? "true" : "false", "\n"); # true

    As you can see, with or without our, $var refers to $main::greet. No variable is created. The purpose of our is to do no strict 'vars'; on a per-variable basis. Like no strict 'vars';, the our directive is lexically scoped (although the variable isn't).

    Remember that I said "mostly true". The exception is when the scope of the our spans packages.

    package Test; $var = "value"; print($Test::var eq "value" ? "true" : "false", "\n"); # true
    our $var; package Test; $var = "value"; print($Test::var eq "value" ? "true" : "false", "\n"); # false
Re: OUR declaration
by shmem (Chancellor) on Sep 23, 2006 at 07:26 UTC
    As davido said, our variables create an entry in the packages symbol tables in which they are declared, while a my variable doesn't. A my variable hides an existing (package) global from that point on to the rest of the variable's scope. That scope is always within the same file and can be delimited with blocks.
    $ourVAR = "123 ABC"; { my $ourVAR = "456 RST"; print "my packAA ourVAR = $ourVAR \n"; } print "our packAA ourVAR = $ourVAR \n"; __END__ my packAA ourVAR = 456 RST our packAA ourVAR = 123 ABC

    In your example, you don't delimit the scope for the my version of $ourVAR, so it's valid unto the rest of the file.

    our variables are shared variables in two ways: they are visible to code

    • of different packages in the same file
      package Foo; our $foo = 'bar'; package main; print $foo,"\n"; # bar
    • in different files belonging to the same package
      # file foo.pl use strict; our $shared = "one fish";
      # file bar.pl use strict; our $shared =~ s/e f/e half f/;
      #/usr/bin/perl use strict; our $shared; require "foo.pl"; require "bar.pl"; print $shared,"\n"; __END__ one half fish

    They behave just like they are qualified - with my, and our.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Your points are true, but they probably need both repeatition and clarification. I provide two examples to clarify your points, for the earlier ones were too simple.

      Example 1. Here we show that the our var can also overide the scope of the my var: the winner is the one who declares last:

      my $foo = 1; our $foo = 2; print $foo ; # prints 2
      The result will be different when we reverse the order of declaration:
      our $foo = 2; my $foo = 1; print $foo ; # prints 1

      Example 2. Here we show that inter-package scopes are only valid during 'no strict'; plus, access to the our variable is possible only if the LEXICAL scope of the our variable is still in force (that is, it reins through the whole file and is not limited just to a block):

      no warnings; package Foo; use Data::Dumper; { our $foo = 'bar'; } print 'Foo: '. $foo, "\n"; # prints 'bar' package Bar; no strict; print 'Bar: '. $foo, "\n"; # $foo is undefined
      Having already acknowledged that there were no mistatements in your post, these exaples were meant only as repeatition to the concepts you have already advanced. Same concepts through different examples.
Re: OUR declaration
by hgolden (Pilgrim) on Sep 23, 2006 at 02:35 UTC
    My copy of Programming Perl is at work, but I seem to recall it saying that the most common use is to make programs compliant with use strict in a giant declaration at the top of the code.

    You can also check out our for some more information.

    Hays

      You can use my for that too. About the only time a package variable is needed is when a variable is accessed from outside the package in which it resides.
        You cannot use local on lexically scoped variables. This is a totally artificial restriction but it means that in those (rare) ocasions when the semantics of local are the tidiest way to implement something you need to use package variables.

        Perl does not support nested named subroutines. If you need nested subroutines you can use anonymous subroutines but this makes stackdumps nigh-on unreadable. Using file-scoped lexicals with local() would be a solution but as I said before you can't do that. So the next best thing is our().

        I once wrote some twisted recursive code to render tables of tables in HTML. Sometimes it would cluck() and I'd get a backtrace with a dozen levels of anonynous subroutine.

        use AtExit; sub awful { my ($various,%shared,@vars); my ($recusive1,$recursive2); my $cleanup = AtExit->new(sub{ undef $recursive1; undef $recursive2; }); $recursive1 = sub { # Do stuff with $various,%shared,@vars and make further calls +to # $recursive1->() and $recursive2->() } $recursive2 = sub { # Do stuff with $various,%shared,@vars and make further calls +to # $recursive1->() and &$recursive2->() and call frobnicate($recursive1); } $recursive1->(); }

        I decided it was more maintainable as:

        our ($various,%shared,@vars); sub awful { local ($various,%shared,@vars); recursive1(); } sub recursive1 { # Do stuff with $various,%shared,@vars and make further calls to # recursive1() and recursive2() } sub recursive2 { # Do stuff with $various,%shared,@vars and make further calls to # recursive1() and recursive2() frobnicate(\&recursive1); }

        Note that frobnicate may call awful() but this inner awful() would not want to share the outer awful()'s variables.

        Now there is a potential problem here if frobnicate() store its CODE reference argument somewhere and thus manages to call back to recursive1() after awful() completes or for that matter during a reentrant call of awful(). But I happened to know that wasn't going to happen.


        There's a similar problem to the nested subroutine problem with regex containing (?{}) except you don't get the warning.

        use strict; use warnings; sub foo { my $x = shift; print "$x "; sub foo1 { print "$x "; # Warning } foo1(); '' =~ /(?{ print "$x\n" })/; # No warning } foo('Hello'); # Prints 'Hello Hello Hello' foo('Goodbye'); # Prints 'Goodbye Hello Hello' sub bar { local our $x = shift; print "$x "; sub bar1 { print "$x "; } bar1(); '' =~ /(?{ print "$x\n" })/; } bar('Hello'); # Prints 'Hello Hello Hello' bar('Goodbye'); # Prints 'Goodbye Goodbye Goodbye' __END__
Re: OUR declaration
by sgifford (Prior) on Sep 23, 2006 at 17:10 UTC

    I usually use our in preference to use vars because it allows a declaration and assignment in one go:

    our $globalvar = 10;

    For global variables, I usually use our in preference to my because it doesn't create closures within subs, which can cause problems under mod_perl.

      When using our as an alternative to my in pseudo-CGI scripts that'll be running under mod_perl I recommend getting into the habit of using local our so that you get a pseudo "global destruction" at the end of the pseudo-CGI script.

      Otherwise, if the declaration doesn't initialise, the value from a previous execution of the script may persist and also if there are any destruction side effects (like closing files) these may get deferred.

        I don't reccommend using our "as an alternative to my" under mod_perl. They don't do the same thing, and mod_perl doesn't change that. If you are using "our" because your code has unintentional closures around "my" variables that showed up when you used mod_perl, you should really change your code to fix this problem. It can bite you in other ways, and "local our" is a pretty nasty construct.
Re: OUR declaration
by ayrnieu (Beadle) on Sep 23, 2006 at 03:08 UTC
    In fact, on a peculiar codebase, I did use our several times in the main part of the program, which had several packages in one file. I've never otherwise bothered with it.