Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
According to the official documentation, the scope of an 'our' variable should be limited to the file in which it's declared, but that is not the case. Is the documentation wrong, or am I just reading it wrong? The doc says an 'our' is visible across its entire lexical scope, which is defined as the enclosing block, file, or eval. Doesn't that also imply the converse... that it's NOT visible OUTSIDE of its lexical scope?
From http://www.perldoc.com/perl5.8.4/pod/func/our.html :
An our declares the listed variables to be valid globals within the enclosing block, file, or eval. That is, it has the same scoping rules as a "my" declaration... ...An our declaration declares a global variable that will be visible across its entire lexical scope, even across package boundaries.
Re: 'our' scoping
by blokhead (Monsignor) on Jun 01, 2004 at 23:34 UTC
|
our $x;
I don't see a question either. Lexical scoping rules are pretty straight-forward as to what parts of the code are within some scope, so I bet you are confusing the scope of the variable itself (the value/data that $x points to) and the scope of this name for the variable (the binding).
With our, we are dealing with package variables, so the variable's data is always accessible (from any namespace) provided we use the fully-qualified name $package::x. our has no scope-induced side effects on the value at $x like local does -- i.e, the value at $x does not disappear when you leave the scope of our $x;.
What our really does is bind the (shorthand) name $x to the appropriate package variable location. The scope of this name binding is what is lexical, not the lifespan of the package variable or its contents. When you fall out of the scope, you lose access to the package variable via the shorthand name $x and that's it. But its value remains, and you can still get to it with its fully qualified name. Outside the scope, you are free to reuse the name $x for a lexical again.
It may sound like hair-splitting, but it's this important distinction that will help you understand the different scoping rules.
| [reply] [d/l] [select] |
Re: 'our' scoping
by tilly (Archbishop) on Jun 01, 2004 at 23:31 UTC
|
If you're asking this question, then odds are that you wanted my rather our. Not that I'm a fan of our at the best of times, for reasons that Why is 'our' good? make clear. | [reply] |
•Re: 'our' scoping
by merlyn (Sage) on Jun 02, 2004 at 09:58 UTC
|
I wrote a recent column on that very subject. In brief, "our" permits a global (package) variable to be accessed within a lexical scope. The confusing thing is that the package used for the lexical alias is the current package at the time of the "our".
| [reply] |
Re: 'our' scoping
by dave_the_m (Monsignor) on Jun 01, 2004 at 23:17 UTC
|
'our' is just a lexically-scoped compiler directive altering the behviour of 'use strict' for a global variable. The variable is still accessible from all all parts of a program, but within the scope of the 'our' declaration,
it is immune from the ravages of 'use strict', eg
$foo = 1;
use strict;
{
our $foo;
$foo++; # $::foo now 2
}
{
no strict;
$foo++; # $::foo now 3
}
# dies with
# Global symbol "$foo" requires explicit package name
$foo++;
Dave. | [reply] [d/l] |
|
Your description of how our works is subtly wrong. The following demonstrates this, without any strict in the way.
package foo;
our $foo = "I'm in foo";
package bar;
our $foo = "I'm in bar";
package foo;
print "1) $foo\n2) $foo::foo\n3) $bar::foo\n";
Note that our caused you to access $bar::foo even when you'd have otherwise expected to access $foo::foo.
For giggles and grins, mix our with $_ when you aren't in package main. Tons of confusion! | [reply] [d/l] |
Re: 'our' scoping
by borisz (Canon) on Jun 01, 2004 at 23:21 UTC
|
And the question was what?
Do not forget that our defines a global var. Maybe you expect what local does?
| [reply] [d/l] [select] |
Re: 'our' scoping
by eclark (Scribe) on Jun 01, 2004 at 23:27 UTC
|
use strict;
package foo;
our $bar = 1;
Is the same as...
use strict;
package foo;
use vars qw/$bar/;
$bar = 1;
And the same as...
use strict;
$foo::bar = 1;
And the same as...
package foo;
$bar = 1;
Sorry for all the strict, but I wanted to show which ones work without a problem in strict. Please correct me if I'm wrong. | [reply] [d/l] [select] |
|
use strict;
package foo;
our $bar = 1;
# at this point, using $bar could mean TWO things:
# 1) try to access the global $foo::bar
# 2) try to access the alias named $bar for $foo::bar
# The lexical (second) one wins in perl, so you don't
# get a use strict error
print $bar;
package baz;
# Now $bar could mean:
# 1) try to access the global $baz::bar
# 2) try to access the alias named $bar for $foo::bar
# The lexical (second) one still wins.
print $bar; # works, prints $foo::bar even though we are in baz
with:
use strict;
package foo;
use vars qw/$bar/;
$bar = 1;
# $bar has only one meaning, access $foo::bar
print $bar;
package baz;
# $bar has only one meaning, access $baz::bar
print $bar; #error
To answer the original question, the documentation is right,
the our (as used in the first code fragment) has no effect outside the file. But... you can still access the global $foo::bar
from another file. But this is NOT using the "our" alias as you can for example see by trying to do in that other file:
package foo;
print $bar; # prints the global $foo::bar
package baz;
print $bar; # prints the global $baz::bar
The lexical alias is gone, and $bar just accesses the global in the package that is in scope. | [reply] [d/l] [select] |
|
Thankyou thankyou thankyou...
You have fixed many confusions that I had. I thought that 'use vars' and 'our' were identical, and it did cause me some confusions because some of my code has a mixture of both (pre 5.6 and post 5.6).
I went back and re-read the our documentation in the camel book and it is very precise, and now I understand (I think) what it is talking about.
However, when I went back and re-read the use vars documentation in the camel book, I realize the source of my confusion...
quote (my italics)
use vars qw($frobbed @munge %seen);
This pragma, once used to declare a global variable, is now somewhat deprecated in favor of the our modifier. The previous declaration is better accomplished using :
our ($frobbed, @munge, %seen);
...
No matter which of these you use, remember that they're talking about package globals, not file-scoped lexicals.
This information had led me astray (it may be technically correct, but it confused me nonetheless).
In closing, I would be really appreciative if you would turn your post into a mini-tutorial.
Thanks,
Sandy
| [reply] [d/l] [select] |
|
|