Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

the "our" declaration ?!!

by perlpal (Scribe)
on Jan 20, 2009 at 04:54 UTC ( #737478=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I've been trying to understand the "our" declaration and its "purpose" and am still confused about the same. I've gone through the tutorials but not really understood the concept. The definition that i've read is "our declares a variable as a package variable within its lexical scope". Please could i have a little more help here ? Thanks in advance.

Replies are listed 'Best First'.
Re: the "our" declaration ?!!
by ikegami (Patriarch) on Jan 20, 2009 at 04:56 UTC

    It's kinda like no strict 'vars';, but it only applies to a single variable.

    It means "yes, a package variable with that name exists, so don't complain about it."

      The strict pragma only protects the current namespace as you can see in some oneliner examples below.
      # set variable, check items in PKG symbol table $ perl -Mstrict -e '$PKG::foo=1; print keys %PKG::' foo $ perl -Mstrict -e '$foo=1; print keys %main::' Global symbol "$foo" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors. $ perl -Mstrict -e 'our $foo=1; print grep {/foo/} keys %main::' foo

      print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});

        I don't understand what you are saying, and your code doesn't contradicts anything I said.

        >perl -Mstrict -le"{ package PKG; $foo=1; }" Global symbol "$foo" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors. >perl -Mstrict -le"{ package PKG; no strict 'vars'; $foo=1; } print fo +r grep /foo/, keys %main::" >perl -Mstrict -le"{ package PKG; our $foo=1; } print for grep /foo/, +keys %main::" >perl -Mstrict -le"{ package PKG; no strict 'vars'; $foo=1; } print fo +r grep /foo/, keys %PKG::" foo >perl -Mstrict -le"{ package PKG; our $foo=1; } print for grep /foo/, +keys %PKG::" foo
        The strict pragma only protects the current namespace

        No, remove the use strict; and the below will run without complaint.

        package X; use strict; sub one { 1 } package Y; $yy = 1; package main; exit; __DATA__ Global symbol "$yy" requires explicit package name at x line 6. Execution of x aborted due to compilation errors.
        Be well,
        rir

        Update: added initial quote for clarity

      It's kinda like no strict 'vars';, but it only applies to a single variable.

      It means "yes, a package variable with that name exists, so don't complain about it."

      Thats a common but incomplete interpretation. "our" works also useful without "strict", so it's not about complaining or not.

      And there are important differences to no strict 'vars', because the chosen namespace can be very different from what you expect: With our it's the stash of the package at declaration position, like with my where it's the lexpad at declaration position.

      But with no strict 'vars' a "non-explicit" variable belongs to the actual package at the encounter position!

      Cheers Rolf

      UPDATE: So one can't simply refactor a code be replacing no strict 'vars' with a lot of ours for each variablename. You have to take care about the local packages!

        Thats a common but incomplete interpretation.

        Correct, but only if you allow for poorly scoped variables. As I see things, my explanation is complete except in buggy programs. Put curlies around your packages when you have more than one in your file.

Re: the "our" declaration ?!!
by gone2015 (Deacon) on Jan 20, 2009 at 11:49 UTC

    So we understand that use strict 'vars' ; will complain about the use of variables that have not been "declared" -- and very useful that is too. (Remembering that this doesn't apply to package variables referred to by their full name (the name including the package part).

    In the case of my variables this is reasonably obvious and straightforward... my "declares" them.

    You can use vars to "declare" package variables (eg  use vars qw($frob @mung %seen);), see vars -- but that is now "obsolete".

    [For completeness: a package variable exists in the package symbol table, and can be accessed by its full name from any other package; a my variable can be accessed only where it is in lexical scope, and does not exist in the package symbol table. So, a package scalar $bar in the package ha::foo can be accessed from (say) main:: using its full name $ha::foo::bar. (Package variables are also known as global variables.) And, "lexical scope" means within the current BLOCK or file (if not in a BLOCK) -- noting the rules allow while (my $z = ...) to work as you'd assume it did</c>.]

    So, our is roughly equivalent to my, except that it's for package variables. The tricky bit is the scope of an our declaration. our does two things: (a) it creates a package variable, which has global scope; (b) declares the variable's name, and that declaration has "lexical scope", in the same way as my.

    The straightforward thing with packages is to: (a) have only one package per file and have that as the first statement in each file; and (b) use our declarations at the package level (not in any BLOCK). If you do that, then our does exactly what you'd expect.

    You can place an our declaration inside a BLOCK, in which case the name is visible inside the block, and refers to the package variable. Use of the variable outside the scope of the our will trigger an error (under use strict 'vars'). To that extent the variable is "private". However: (a) it is still possible to access the variable using its full name; and (b) another our declaration elsewhere in the package will refer to the same variable. (If you were starting to think of our in terms of static, then stop right now.)

    An our declaration outside any BLOCK has file scope. If you have more than one package in a file, then the name of an our variable in one package will be visible in the later packages in the file, and refers to the declaring package's package variable of that name.

    These effects are illustrated in the code below, and I hope that the comments therein are sufficient to make things as clear as may be expected under the circumstances.

      Thank you for the detailed explanation , it helped in clearing a lot of my doubts.
Re: the "our" declaration ?!!
by dsheroh (Monsignor) on Jan 20, 2009 at 11:11 UTC
    Sometimes you need to create a variable which can be accessed from outside the current package. That's what "our" is for.
    package Foo; my bar; # Nobody outside of package Foo can access bar. our baz; # Anyone can access baz by referring to it as Foo::baz, no # matter what package they're in (provided they use/require # Foo). # # This also allows Foo to export baz, in which case other # packages could import it and refer to it as just "baz".
Re: the "our" declaration ?!!
by LanX (Sage) on Jan 20, 2009 at 10:57 UTC

    "our" has exactly the same scope like "my", it's the exact analogon but for package variables.

    If the compiler encounters a simple* variable name like $var it has to decide where to store and look up it's value. This is decided by the last "declaration"¹ (my or our) within the same "lexical scope", which doesn't necessarily mean the variable itself is "lexical" (that means: private to the lexical scope).

    use warnings; use strict; $\="\n"; $,="\t"; our $x="main"; { package one; our $x="one"; package two; our $y="two"; { my $x="private"; print $x,$y; # private $x , $two::y } # end of second scope print $x,$y; # $one::x , $two::y } # end of first scope print $x; # $main::x print $one::x; # variable still exists in that namespace # without being bound to $x # but the private $x of the second scope # is definitely lost! # end of file scope __END__ private two one two main one
    So "our" gives you a much more orthogonal behavior to "my" than simply relying on "simple variables are by default packagevars except when declared with my"².

    Cheers Rolf

    UPDATES: extended code example

    (*) "simple" means without explicit package name e.g. $package::var

    (¹) I'm not sure if "declaration" is the best term, maybe better "binding" or "aliasing", the perldoc talks about "associating"

    (²) without "strict" or "vars"

    well the explanation in "perldoc -f our" is quite good!

    "our" associates a simple name with a package variable in the current package for use within the current scope. When "use strict ’vars’" is in effect, "our" lets you use declared global variables without qualifying them with package names, within the lexical scope of the "our" declaration. In this way "our" differs from "use vars", which is package scoped.

    Unlike "my", which both allocates storage for a variable and associates a sim‐ ple name with that storage for use within the current scope, "our" associates a simple name with a package variable in the current package, for use within the current scope. In other words, "our" has the same scoping rules as "my", but does not necessarily create a variable.

    ...

Re: the "our" declaration ?!!
by DrHyde (Prior) on Jan 22, 2009 at 10:55 UTC
    "our" is pointless. There is nothing you can do with it that can't be trivially done without it. The only thing it gives you is incompatibility with older perls. I recommend not using it.
      Don't you think that, by this reasoning, all perl development should have stopped at 5.6 or something?
      I think our, combined with use strict and without use vars or qualified variables is a very elegant way of declaring package variables while at the same time maintaining minium scope for them. I suppose we will have to agree in disagreeing, and that TIMTOWTDI.
      []s, HTH, Massa (κς,πμ,πλ)
      I recommend instead not using any perl old enough to lack "our". It's a much better proposition in terms of programmer usefulness. Actually I think that (proper) Unicode support and PerlIO are enough reason that most people should never consider using anything less than 5.8. "our" is lovely when dealing with package globals and "use vars" is nothing more than a mistake.

        Proper Unicode support certainly would be a good reason to not use any earlier version. Unfortunately, perl doesn't have it yet. Unicode needs to "just work" for it to have proper support. It doesn't, as is obvious from a great many posts in this august forum. This isn't entirely perl's fault, of course, as it depends on broken libraries, broken terminals, broken filesystems, broken web browsers (for many use cases), and so on if funny furrin characters are to Just Work. It will be a very long time before Unicode Just Works, because *everything* needs upgrading. So Unicode is a bit of a red herring.

        I see only one thing in the various perldeltas which would persuade me that upgrading a working perl 5.6.2 (and re-testing everything, re-installing all my modules etc) to any subsequent version on any of my machines would be worth it. That one thing is userelocateableinc in 5.10, which is useful on one machine. The only other reasons I run higher versions of perl are:

        • Specifically for testing purposes;
        • Because that's what came with the OS;
        • Because it's easier to download the source for $latest from search.cpan.org;
        • Because someone whose code I depend on used a new feature when he didn't need to, and I'm too lazy to backport his code
        "use vars" is nothing more than a mistake.
        Then perl is a mistake. I think you wish to reconsider.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://737478]
Approved by ikegami
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2022-09-30 13:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    I prefer my indexes to start at:




    Results (126 votes). Check out past polls.

    Notices?