"use strict" in a module

L

Larry

The following code:

package FooPkg;

use strict;
use Exporter ();
use vars qw/@ISA @EXPORT/;
@ISA = qw/Exporter/;
@EXPORT = qw/$x $y $z/;
use vars @EXPORT;

$x = 5;

produces:

Global symbol "$x" requires explicit package name at FooPkg.pm
line 10.
FooPkg.pm had compilation errors.

However, if I change:

use vars @EXPORT;

to

use vars qw/$x $y $z/;

it works. But I would like to avoid repeating the qw/$x $y $z/ . Why
won't the original version work?
 
M

Mumia W.

The following code:

package FooPkg;

use strict;
use Exporter ();
use vars qw/@ISA @EXPORT/;
@ISA = qw/Exporter/;
@EXPORT = qw/$x $y $z/;
use vars @EXPORT;

$x = 5;

produces:

Global symbol "$x" requires explicit package name at FooPkg.pm
line 10.
FooPkg.pm had compilation errors.

However, if I change:

use vars @EXPORT;

to

use vars qw/$x $y $z/;

it works. But I would like to avoid repeating the qw/$x $y $z/ . Why
won't the original version work?

"Use vars ..." is done at compile time, so @EXPORT is unset when the
command is evaluated. For this to work, you must make sure that @EXPORT
is set at compile time too:

package FooPkg;

use strict;
use Exporter ();
use vars qw/@ISA @EXPORT/;
BEGIN {
@ISA = qw/Exporter/;
@EXPORT = qw/$x $y $z/;
}
use vars @EXPORT;

__HTH__

http://perldoc.perl.org/perlsub.html
 
F

Ferry Bolhar

Larry:
use strict;
use Exporter ();
use vars qw/@ISA @EXPORT/;
@ISA = qw/Exporter/;
@EXPORT = qw/$x $y $z/;
use vars @EXPORT;

$x = 5;

produces:

Global symbol "$x" requires explicit package name at FooPkg.pm
line 10.
FooPkg.pm had compilation errors.

However, if I change:

use vars @EXPORT;

to

use vars qw/$x $y $z/;

it works. But I would like to avoid repeating the qw/$x $y $z/ . Why
won't the original version work?

Because "use" is a _compiler_ directive, processed much earlier that the
assignment to @EXPORT which gets executed at _run-time_. When
the

use vars @EXPORT;

is processed (and the resultant module code gets executed), @EXPORT
doesn't yet contain any variable names, so the "use vars" has nothing to do
(similar to a "use vars;").

One could write

BEGIN {
@EXPORT = qw/$x $y $z/;
}
use vars @EXPORT;

and it should work as expected, but I'd avoid code techniques like this,
because it makes your code harder to read.

Greetings, Ferry
--
 
B

Ben Morrow

Quoth Larry said:
The following code:

package FooPkg;

use strict;
use Exporter ();
use vars qw/@ISA @EXPORT/;
@ISA = qw/Exporter/;
@EXPORT = qw/$x $y $z/;
use vars @EXPORT;

$x = 5;

produces:

Global symbol "$x" requires explicit package name at FooPkg.pm
line 10.
FooPkg.pm had compilation errors.

However, if I change:

use vars @EXPORT;

to

use vars qw/$x $y $z/;

it works. But I would like to avoid repeating the qw/$x $y $z/ . Why
won't the original version work?

As has been explained, you would need to assign to @EXPORT at compile
time. There is a pragma on CPAN, vars::i, which will do this for you, so
you could say

use vars::i '@EXPORT' => qw/$x $y $z/;
use vars @EXPORT;

but in any case 'use vars' is considered bad style nowadays (since perl
5.6). The currently recommended way to write the above would be

use strict;

use Exporter ();
our @ISA = qw/Exporter/;

our ($x, $y, $z);
our @EXPORT = qw/$x, $y, $z/;

which still leaves you repeating the list of variables... consider it a
'tax' on exporting things. You should not export (especially variables)
without good reason :).

(Note that in the presence of subsequent 'package' statements, the
behaviour of 'our' is not quite the same as that of 'use vars'. For
instance, given

package A;
our $foo;

package B;
print $foo;

$foo refers to $A::foo, not $B::foo.)

Ben
 

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,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top