Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re: Note on usage of ours variables and a question

by haukex (Bishop)
on Nov 19, 2019 at 23:01 UTC ( #11108915=note: print w/replies, xml ) Need Help??

in reply to Note on usage of ours variables and a question

I think the best approach depends on the specific application, which you haven't described very much. Of course TIMTOWTDI, but I would suggest that instead of the modules exporting a debug variable or something similar, the main script should instead set the debug flag on the module. So for example, if I write OO classes, I might give the constructor a debug argument that is set based on a $DEBUG package variable in the main script. If it's a simple module, it might have its own our $DEBUG variable in its package, and then the main code could do $Module::Name::DEBUG = $DEBUG. This will allow you to use the $DEBUG variable name everywhere, and still keep the possibility of somewhat more fine-grained control, instead of one global debug flag that enables debug messages everywhere. So like this is how I typically do it:

use warnings; use strict; use Getopt::Long; GetOptions( 'd|debug' => \(our $DEBUG) ) or die "Bad options\n"; $Foo::DEBUG = $DEBUG; print "Debugging main\n" if $DEBUG; Foo::foo(); my $bar = Bar->new( debug => $DEBUG ); $bar->quz(); { package Foo; our $DEBUG; sub foo { print "Debugging Foo\n" if $DEBUG; } } { package Bar; sub new { my ($class,%args) = @_; my $self = { %args }; return bless $self, $class; } sub quz { my $self = shift; print "Debugging $self->quz()\n" if $self->{debug}; } }
Also question about 'export" behavior". If I export variable debug from module A does it became "normal variable" in main:: so that I can use it in module B? what will happen if I export it from module b as well ? It should bind it to the same variable, right?

If I understand your question correctly, then no, two different exports will overwrite each other. If you have a module X with our $Z that gets exported to main, and then a module Y with our $Z that also gets exported to main, the second export will clobber the first. Consider that you've got two variables, one in each package, and so the variable $main::Z can only be an alias for one or the other.

use warnings; use strict; BEGIN { package X; use me::inlined; # alternative: $INC{__PACKAGE__.'.pm'}=$0; use Exporter 'import'; our @EXPORT = qw/$Z/; our $Z = 'from '.__PACKAGE__; } BEGIN { package Y; use me::inlined; # alternative: $INC{__PACKAGE__.'.pm'}=$0; use Exporter 'import'; our @EXPORT = qw/$Z/; our $Z = 'from '.__PACKAGE__; } use X; use Y; print "$Z\n"; # prints "from Y"

Although I wouldn't recommend it (!), you could have all your modules reference $main::DEBUG with the shorthand $::DEBUG, or even alias the package variables to $main::DEBUG, then you'd only have one central variable. However, the problems with this are that you lose the fine-grained control of the debug flag, and also if these modules are loaded into code that doesn't know about their behavior (remember modules are meant to be re-used), things might break when those modules reach outside of their package into variables that aren't really theirs.

Can anybody enlighten me about this behavior?

I would suggest a careful read of the sections "Packages" and "Symbol Tables" in perlmod (the rest of the document is also very interesting).

BTW does Perl have a system variable "debug" that is global and does not need qualification with the package name?

No, not that I'm aware of in the core.

Why we can't alias variables in other namespaces? Is not this an artificial restriction?

It's possible - you'd have to show an instance of where it isn't working for you.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11108915]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2021-01-16 05:14 GMT
Find Nodes?
    Voting Booth?