Re: local our?
by ikegami (Patriarch) on Apr 04, 2006 at 21:54 UTC
|
local and our are completely unrelated. For now, let's expand the code and look at the statements individually.
our $bob;
local $bob;
$bob = 'bob';
-
our $bob; disables use strict 'vars' for $bob for the remainder of current scope. It allows you to use package variable $bob without its package name where you might have had to without our $bob;. [Note that this is a bit of an oversimplification. (Upd)]
-
local $bob; saves the current value of $bob (and sets $bob to undef). When the scope is exited (whether normally or by exception), $bob reclaims the value saved by local $bob.
-
$bob = 'bob'; assigns a value to $bob.
Now, let's put these into context.
Say you wish to take advantage of dynamic scoping. That means you need to use a package variable, not a lexical (my) variable. To avoid having to specify the package name when using that package variable, you use our. Let's also say you wish to protect the value that's currently being held by this variable. local would be used.
Why would you want to use dynamic scoping? Maybe you want to override a global option temporarily. For example,
use strict;
use warnings;
package MyModule;
sub do_it {
my ($arg) = @_;
our $VERBOSE;
...
warn(...)
if $VERBOSE;
...
}
sub do_it_quietly {
my ($arg) = @_;
our $VERBOSE; # Avoid saying $MyModule::VERBOSE
local $VERBOSE; # Save existing value.
$VERBOSE = 0; # Disable logging.
do_it($arg);
}
1;
Finally, since local and our return their arguments as lvalues, it's possible to chain these functions. For example, the following are all equivalent:
- our $VERBOSE; local $VERBOSE; $VERBOSE = 0;
- our($VERBOSE); local($VERBOSE); $VERBOSE = 0;
- local(our($VERBOSE)) = 0;
- local our $VERBOSE = 0;
| [reply] [d/l] [select] |
|
|
local and our are completely unrelated.
That's not true. local is about aliasing package globals, and our creates a package global in the package where that declaration occurs (and a lexical alias to that in the current scope), so they are related: they both act upon slots in the symbol table of a package. So they are related.
$ perl -E 'package Foo; local our $bar; package main; say for keys %Fo
+o::'
bar
and
$ perl -E 'our $bar = "foo"; say "1: $bar"; package Foo; { local our $
+bar = "quux"; say "2: $bar"; }; say "3: $bar"; package main; say "4:
+$bar"; say "Foo::$_" for keys %Foo::'
1: foo
2: quux
3: foo
4: foo
Foo::bar
perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
| [reply] [d/l] [select] |
|
|
The fact that they both can take a package variables as an argument doesn't make them related in any meaningful way.
local is about aliasing package globals
No. For example, my %h; local $h{x};. It's about making temporary backups of some values.
our creates a package global
No. our creates a lexical variable (that's aliased to the specified package variable).
Simply mentioning the package var is what creates it.
$ perl -le' print $::{var} // "[undef]"'
[undef]
$ perl -le'$var; print $::{var} // "[undef]"'
*main::var
| [reply] [d/l] [select] |
|
|
I think it's important to stay accurate:
> our creates a package global in the package where that declaration occurs
our will create a new STASH entry only, iff it doesn't already exist and it will not touch the value.
> local is about aliasing package globals
I can't see any "aliasing" process here, it's still the same underlying package variable.
what do you call an "alias" here when doing local $main::bob; ?
| [reply] [d/l] |
|
|
{
local our $bob;
#no strict 'vars';
$bob = "bob";
warn "$bob\n"; # > bob
package OTHER;
warn "$bob\n"; # > bob
}
{
#local our $bob;
no strict 'vars';
$bob = "bob";
warn "$bob\n"; # > bob
package OTHER;
warn "$bob\n";
# ERR: Use of uninitialized value $OTHER::bob in concatenation
}
> local and our are completely unrelated.
well not completely, since local can't be used for private vars
| [reply] [d/l] [select] |
|
|
our $bob; disables use strict 'vars' for $bob for the remainder of current scope.
For my interest, is that actually how our is implemented, or is that just your way of explaining the effect?
| [reply] |
|
|
> > disables use strict vars for $bob for the remainder of current scope.
> For my interest, is that actually how our is implemented ...
no, see my other answer in this thread.
our $bob is aliasing at compile time a "simple" symbol $bob to a full qualified $__PACKAGE__::bob for the remainder of current scope.
| [reply] [d/l] [select] |
|
|
I'm not sure I understand your question. I didn't mention any algorithm, so I don't see how I could have spoken of implementation. I described its function and its effect.
| [reply] |
|
|
|
|
|
|
Just a warning: "Finally, since local and our return their arguments as lvalues, it's possible to chain these functions" implies that
our local $var
should also be equivalent. It's not: Perl returns the error:
No such class local at ..., near "our local"
In the end,
local our $var
is the way to go when you need to do this.
| [reply] [d/l] [select] |
|
|
Thanks for your great example. I never could think of a practical use for 'our' because it never occurred to me that the same name could be declared in more than one scope and that both would refer to the same variable. This is a great solution to the problem of initializing a variable in a BEGIN block and using it in the main code.
| [reply] |
Re: local our?
by codeacrobat (Chaplain) on Apr 04, 2006 at 21:45 UTC
|
our $bob declares the scalar variable $bob in the current package. local localizes $bob in the current code block.
$bob = "billy";
{
local our $bob = "bob";
print $bob; # prints "bob", hides the $bob from outside the block
};
print $bob; # actually prints "billy", because the local scope is gone
| [reply] [d/l] |
Re: local our?
by LanX (Saint) on Apr 14, 2019 at 20:18 UTC
|
our is a compile-time declaration for package variables like my for private variables.
our is lexically aliasing $bob to $PKG::bob (the "fully qualified name")
"Lexically" means here till the end of the surrounding scope
PKG is the current package name, i.e. main by default.
It's important to understand that the variable is global and won't be destroyed at the end of the scope, like with private my-variables. Only the alias is disappearing.
local is a runtime directive to save the variables value and restore it at the end of the scope. local is the builtin mechanism to avoid global consequences to package vars. (Perl4 didn't have private my-vars, and unfortunately one "can't localize lexical variable" ³)
> Where and why would I use
You can write our $bob multiple times to avoid the need to write $PKG::bob inside dedicated scopes. But it won't create a new local variable like my does.
local our $bob = 'bob'; will protect the old value from being overwritten by "bob".
It's a shortcut for writing 2 statements our $bob;local $bob ="bob"; *)
use strict;
use warnings;
use Data::Dump qw/pp dd/;
$main::bob = "by"; # fully qualified global var
warn "$main::bob\n"; # > by
{
our $bob = "tail"; # lexical alias
warn "$bob\n"; # > tail
}
warn "$main::bob\n"; # > tail
# warn "$bob\n";
# ERR: Global symbol "$bob" requires explicit package name
{
local our $bob = "bob"; # protect from global effects
warn "$bob\n"; # > bob
package OTHER;
warn "$bob\n"; # > bob (still aliased to $main::b
+ob ²)
}
warn "$main::bob\n"; # > tail
So yes, there are circumstances where it's pretty useful to write local our $var
HTH! =)
UPDATE
*) logical error corrected, thanks to choroba to notice the glitch.
²) This demonstrates an essential often ignored difference to "use vars ;"
³) it's unfortunate that "lexical var" is synonymously used for "private var", since like demonstrated, our has a lexical effect. | [reply] [d/l] [select] |
Re: local our?
by Anonymous Monk on Apr 04, 2006 at 21:42 UTC
|
Use it when, otherwise, you'd use local $Foo::bob; | [reply] |