0

I have a module misc with variable $verbose:

use strict;
use diagnostics;
package misc;
my $verbose = 1;

and module mymod which uses misc:

use strict;
use diagnostics;
use misc;
package mymod;
sub mysub ($) {
  ...
  ($misc::verbose > 0) and print "verbose!\n";
}

which is, in turn, used by myprog:

use strict;
use diagnostics;
use misc;
use mymod;
mymod::mysub("foo");

when I execute myprog, I get this warning:

Use of uninitialized value $misc::verbose in numeric gt (>) at mymod.pm line ...

what am I doing wrong?

sds
  • 58,617
  • 29
  • 161
  • 278
  • 1
    BTW Using modules before declaring a package is subtly wrong. Things like `use strict` and `use diagnostics` happen to work because they are lexical (ie. what block they are in) and do not care about packages, but others DO care about what package they are in, especially if they export functions. – Schwern Aug 14 '12 at 17:46
  • so, it should be "package mymod; use ..." ? thanks. – sds Aug 14 '12 at 19:27

1 Answers1

3

In mymod.pm you should be using:

our $verbose = 1;

instead of:

my $verbose = 1;

The warning is because $misc::verbose tries to access the package variable $verbose in the misc package, which incidentally, is not declared.

The my function creates a lexically scoped variable. In this case, you require a package scoped variable, which is created by using the our function.

Please pay attention to daxim's comment.

Community
  • 1
  • 1
Alan Haggai Alavi
  • 72,802
  • 19
  • 102
  • 127
  • 3
    This works, but [good programming practice prescribes that you do not allow foreign code to mess with a module's data directly, instead they must go through an intermediary, for example an accessor routine](http://stackoverflow.com/a/3110097). See those first two code examples. – daxim Aug 14 '12 at 17:37
  • Also check out [Exporter](http://search.cpan.org/~toddr/Exporter-5.66/lib/Exporter.pm) if you want to export subroutines and/or variables – John Corbett Aug 14 '12 at 18:03
  • 1
    To add to daxim's comment - please do NOT build accessor methods by hand ala Java or C++. For older Perls, use `Class::Accessor::Fast`, or for newer, use Moose. – DVK Aug 14 '12 at 18:54
  • As a counterbalance to @daxim's comment, sometimes it is quite natural to expose package variables thus. This is especially so for procedural interfaces with runtime parameters that the coder might want to change (perhaps via `local()`izing). Consider `$Data::Dumper::Purity`, `$Carp::Verbose`, `$IPC::Cmd::ALLOW_NULL_ARGS`, and so forth. – pilcrow Aug 14 '12 at 20:37
  • These are really crappy interfaces from a time when people didn't know better. Setting a package variable makes it difficult to use several instances in a program and provokes weird to debug action-at-a-distance effects. Objects don't have that flaw, so use Moose. – daxim Aug 15 '12 at 12:27