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? :)
| [reply] [d/l] [select] |
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. | [reply] |
|
| [reply] |
|
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. | [reply] [d/l] [select] |
|
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.
| [reply] |
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
| [reply] [d/l] [select] |
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}
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] [select] |
Re: OUR declaration
by hgolden (Pilgrim) on Sep 23, 2006 at 02:35 UTC
|
| [reply] [d/l] |
|
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.
| [reply] [d/l] |
|
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__
| [reply] [d/l] [select] |
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.
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] [select] |
|
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.
| [reply] |
|
|
|
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. | [reply] [d/l] |