Modules, global variables and such

J

January Weiner

Hello,

I have the following problem. I had a script that contained only one
global variable which was called $DEBUG. I just used it to print out
various think or do some checks in debugging mode

print "number of objects $n_obj\n" if $DEBUG ;
check_sanity if $DEBUG ;

The program grew and now I splitted it up into several modules.

Question: what to do with the debug variable?

* I could make it local to all of the functions, but I would really hate
passing it through to each of the functions separately. Firstly, IMO this
is one of the few cases where global variables are justified, and second,
this would require me to make hundreds of modifications in the code.

* I could make it a global variable in each of the modules, and create a
function that switches on the debugging for one module only. This would
have the advantage that I could specify which module to debug.
Disadvantage is that I need to remember to switch it on in every module
if I want to switch it on globally.

* Finally, I could make a separate module with generic tests for sanity and
printing warning messages, and that module would hold the only instance
of the $DEBUG variable. Again, many modifications in the code required.

Of course, I can imagine that there are gazillions of other ways of doing
that, and that there are specific modules that do precisely what I want.
What route would you recommend?

Regards,

January
 
G

Gunnar Hjalmarsson

January said:
I have the following problem. I had a script that contained only one
global variable which was called $DEBUG. I just used it to print out
various think or do some checks in debugging mode

print "number of objects $n_obj\n" if $DEBUG ;
check_sanity if $DEBUG ;

The program grew and now I splitted it up into several modules.

Question: what to do with the debug variable?

* I could make it local to all of the functions, but I would really hate
passing it through to each of the functions separately. Firstly, IMO this
is one of the few cases where global variables are justified, and second,
this would require me to make hundreds of modifications in the code.

* I could make it a global variable in each of the modules, and create a
function that switches on the debugging for one module only. This would
have the advantage that I could specify which module to debug.
Disadvantage is that I need to remember to switch it on in every module
if I want to switch it on globally.

* Finally, I could make a separate module with generic tests for sanity and
printing warning messages, and that module would hold the only instance
of the $DEBUG variable. Again, many modifications in the code required.

You didn't mention the simplest way:

Keep it a global variable in one of the modules and use its fully
qualified name when calling it from other modules, e.g. $MyModule::DEBUG
 
J

January Weiner

You didn't mention the simplest way:
Keep it a global variable in one of the modules and use its fully
qualified name when calling it from other modules, e.g. $MyModule::DEBUG

This is more or less my third way. It requires modifying each of the
statements containing $DEBUG and including the module in all the other
modules and the main code. But yes, I am considering this, thanks!

j.
 
J

January Weiner

Abigail said:
You seem to have the impression that if you're using a variable
$MyModule::DEBUG, you have to have a MyModule.pm, and you have
to 'use' that file.
That's not true.

package Fnurd;
use strict;
use warnings;
say "Hi, I'm a debugging message." if $MyModule::DEBUG;

Ah, OK. I always used only functions exported from modules or OO modules.
These must be exported and the modules must be imported. I assumed that the
same holds for the variables.

j.
 
J

January Weiner

Abigail said:
That's what I usually do, except that put the variable in main, so I
can just use $::DEBUG.

This is it! Thank you (both) very much.
srand 123456;$-=rand$_--=>@[[$-,$_]=@[[$_,$-]for(reverse+1..(@[=split
//=>"IGrACVGQ\x02GJCWVhP\x02PL\x02jNMP"));print+(map{$_^q^"^}@[),"\n"

'eresal nPhkuHrJ cteatro'? There is something disconcerting in this
message...

j.
 
A

Andreas Pürzer

Abigail said:
You seem to have the impression that if you're using a variable
$MyModule::DEBUG, you have to have a MyModule.pm, and you have
to 'use' that file.

That's not true.


package Fnurd;

use strict;
use warnings;

say "Hi, I'm a debugging message." if $MyModule::DEBUG;


works well.


Abigail

For curious lurkers like me, soaking up wisdom from c.l.p.m, I think it
should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
for this to work, because:

$ perl -Mstrict -Mwarnings -le'
package MyModule;
my $DEBUG = 1;
package Fnurd;
print "Debug on" if $MyModule::DEBUG;
'
Name "MyModule::DEBUG" used only once: possible typo at -e line 5.

whereas with 'our':

$ perl -Mstrict -Mwarnings -le'
package MyModule;
our $DEBUG = 1;
package Fnurd;
print "Debug on" if $MyModule::DEBUG;
'
Debug on


But then I don't even have to use the fully qualified name:

$ perl -Mstrict -Mwarnings -le'
package MyModule;
our $DEBUG = 1;
package Fnurd;
print "Debug on" if $DEBUG;
'
Debug on


Toying a little more, I find that

$ perl -Mstrict -Mwarnings -le'
package MyModule;
my $DEBUG = 1;
package Fnurd;
print "Debug on" if $DEBUG;
'
Debug on

works equally well.

What am I not understanding?

Thank you,
Andreas Pürzer
 
G

Gunnar Hjalmarsson

Andreas said:
For curious lurkers like me, soaking up wisdom from c.l.p.m, I think it
should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
for this to work, because:

$ perl -Mstrict -Mwarnings -le'
package MyModule;
my $DEBUG = 1;
package Fnurd;
print "Debug on" if $MyModule::DEBUG;
'
Name "MyModule::DEBUG" used only once: possible typo at -e line 5.

That's because the my() declared $DEBUG and $MyModule::DEBUG are two
different variables...
whereas with 'our':

$ perl -Mstrict -Mwarnings -le'
package MyModule;
our $DEBUG = 1;
package Fnurd;
print "Debug on" if $MyModule::DEBUG;
'
Debug on

But then I don't even have to use the fully qualified name:

$ perl -Mstrict -Mwarnings -le'
package MyModule;
our $DEBUG = 1;
package Fnurd;
print "Debug on" if $DEBUG;
'
Debug on

You do have to use the fully qualified name if you call the variable
from somewhere outside the MyModule package.
Toying a little more, I find that

$ perl -Mstrict -Mwarnings -le'
package MyModule;
my $DEBUG = 1;
package Fnurd;
print "Debug on" if $DEBUG;
'
Debug on

works equally well.

Not if you call it from some other module or from the main script.
What am I not understanding?

Maybe you didn't read the whole thread carefully enough? ;-)
 
B

Ben Morrow

Quoth Gunnar Hjalmarsson said:
You do have to use the fully qualified name if you call the variable
from somewhere outside the MyModule package.

No, not if you use 'our'. An often-overlooked property of 'our' is that
it creates a lexical alias to the package variable: in simple terms, you
can use that variable unqualified for the rest of the lexical scope,
even if you change package. This is why the second example above works
as it does.
Not if you call it from some other module or from the main script.

More precisely: if you attempt to use it in some other lexical scope.
Package statements are irrelevant for lexicals, so if you have some code
in another file that is in package MyModule it still can't see the
lexical.

Ben
 
B

Ben Morrow

Quoth (e-mail address removed):
_
Gunnar Hjalmarsson ([email protected]) wrote on VCCLXXVI September
MCMXCIII in <URL:-: January Weiner wrote:
-: > I have the following problem. I had a script that contained only one
-: > global variable which was called $DEBUG. I just used it to print out
-: > various think or do some checks in debugging mode
-:
-: You didn't mention the simplest way:
-:
-: Keep it a global variable in one of the modules and use its fully
-: qualified name when calling it from other modules, e.g. $MyModule::DEBUG

That's what I usually do, except that put the variable in main, so I
can just use $::DEBUG.

If this code might be used in some other, unrelated program (that is,
the debugging state belongs with the module, not the program as a whole)
you can create a package global and then import it into your other
packages:

package MyModule;

require 'Exporter';
our @ISA = 'Exporter';
our @EXPORT_OK = qw/$DEBUG/;

our $DEBUG;

__DATA__

package MyModule::Foo;

use MyModule qw/$DEBUG/;

# now just use $DEBUG, as before

__DATA__

Ben
 
M

Mark Clements

January said:
Hello,

I have the following problem. I had a script that contained only one
global variable which was called $DEBUG. I just used it to print out
various think or do some checks in debugging mode

print "number of objects $n_obj\n" if $DEBUG ;
check_sanity if $DEBUG ;

This post is orthogonal to the other messages in this thread, but you
may want to check out

Carp::Assert
Log::Log4perl

Mark
 
G

Gunnar Hjalmarsson

Ben said:
No, not if you use 'our'. An often-overlooked property of 'our' is that
it creates a lexical alias to the package variable: in simple terms, you
can use that variable unqualified for the rest of the lexical scope,
even if you change package.

Well, yes, but note that this thread was initially about calling the
$DEBUG variable from other modules, which typically are both different
packages and different lexical scopes. So Andreas' statement, that the
fully qualified name isn't necessary, isn't normally applicable to the
situation that was initially discussed.
 
T

Tad J McClellan

Andreas Pürzer said:
For curious lurkers like me, soaking up wisdom from c.l.p.m, I think it
should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
for this to work, because:


No it doesn't.

$ perl -Mstrict -Mwarnings -le'
package MyModule;
my $DEBUG = 1;


Change that last line above to:

$MyModule::DEBUG = 1;

and it will work fine.

For package variables, strict vars requires EITHER a declaration (if
you want to use the short version of the name (ie. unqualified))
OR a fully-qualified name.

Note that your version uses a "lexical variable". My mod uses
a "package variable".

package Fnurd;
print "Debug on" if $MyModule::DEBUG;
'
Name "MyModule::DEBUG" used only once: possible typo at -e line 5.

whereas with 'our':

$ perl -Mstrict -Mwarnings -le'
package MyModule;
our $DEBUG = 1;
package Fnurd;
print "Debug on" if $MyModule::DEBUG;
'
Debug on


Now your code is using a package variable too.

But then I don't even have to use the fully qualified name:

$ perl -Mstrict -Mwarnings -le'
package MyModule;
our $DEBUG = 1;
package Fnurd;
print "Debug on" if $DEBUG;
'
Debug on


That is because our() is lexically scoped (like it says in perldoc -f our).

In your program above, the our() is scoped to the entire file, so
it is in effect down in the Fnurd package.

Toying a little more, I find that

$ perl -Mstrict -Mwarnings -le'
package MyModule;
my $DEBUG = 1;
package Fnurd;
print "Debug on" if $DEBUG;
'
Debug on

works equally well.


It would not work if the two packages were in different files,
because lexical variables can NEVER cross file boundaries.

What am I not understanding?


Most of it seems to the the difference between lexical variables (my)
and package variables (our or fully-qualified). See

perldoc -q "dynamic and lexical"

and

"Coping with Scoping":

http://perl.plover.com/FAQs/Namespaces.html
 
A

Andreas Pürzer

Tad said:
Andreas Pürzer said:
I think it
should be mentioned that $MyModule::DEBUG needs to be declared via 'our'
for this to work, because:



No it doesn't.

For package variables, strict vars requires EITHER a declaration (if
you want to use the short version of the name (ie. unqualified))
OR a fully-qualified name.

Note that your version uses a "lexical variable". My mod uses
a "package variable".



[snip]

It would not work if the two packages were in different files,
because lexical variables can NEVER cross file boundaries.


What am I not understanding?



Most of it seems to the the difference between lexical variables (my)
and package variables (our or fully-qualified). See

perldoc -q "dynamic and lexical"

and

"Coping with Scoping":

http://perl.plover.com/FAQs/Namespaces.html

I've already read those, but it seems it's time to read them again...
And like Gunnar suggested, I will try to read them much more carefully
this time ;->

Thanks to all who responded,
Andreas Pürzer
 
A

Andreas Pürzer

Gunnar said:
Well, yes, but note that this thread was initially about calling the
$DEBUG variable from other modules, which typically are both different
packages and different lexical scopes. So Andreas' statement, that the
fully qualified name isn't necessary, isn't normally applicable to the
situation that was initially discussed.

Oops, an Usenet-Thread gone sideways with me to blame, sorry about that ;->
SCNR

Thanks to both of you,
Andreas Pürzer
 
G

Gunnar Hjalmarsson

Andreas said:
Oops, an Usenet-Thread gone sideways with me to blame, sorry about that ;->
SCNR

That's absolutely not a problem; as a matter of fact it happens all the
time, and it makes Usenet discussions more interesting. :)

My point was rather about context. Your code examples were posted in a
context, and you'd better be aware of the context when discussing them.
 
A

Andreas Pürzer

Gunnar said:
That's absolutely not a problem; as a matter of fact it happens all the
time, and it makes Usenet discussions more interesting. :)

hence the SCNR said:
My point was rather about context. Your code examples were posted in a
context, and you'd better be aware of the context when discussing them.

Point taken. But if I hadn't misinterpreted context, I hadn't learnt
from this discussion. Maybe this is what perldiag calls 'Unbalanced
context'? :)

Thank you,
Andreas Pürzer
 
J

January Weiner

Thanks for all the answers, I learned a lot. I now use $::DEBUG for my
purposes.

Cheers,
j.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top