Stuart
Stuart

Reputation: 1773

How to use a package with a variable name

My end goal is to use an argument as the package. I can't get a simple example to work though. Is there a way to use a $variable as my package?

MyModule.pm

package MyModule;
use strict;
use warnings;
use parent 'Exporter'; # imports and subclasses Exporter

our $test="hello world\n";
our @EXPORT = qw($test);

program.pl

#!/usr/bin/perl
use strict;
use warnings;

my $x = 'MyModule.pm';
eval "require $x";
MyModule->import;
print "$test\n";

Error

Global symbol "$test" requires explicit package name at ./program.pl line 8.
Execution of ./program.pl aborted due to compilation errors.

Upvotes: 0

Views: 778

Answers (1)

ysth
ysth

Reputation: 98398

require has two syntaxes; one expects an unquoted package name (e.g. require Foo::Bar;), the other expects an expression that yields a filename (e.g. require "Foo/Bar.pm";). Note that the latter still searches the library directories, and works with / between components even on systems that use other path separators.

Your:

my $x = 'MyModule.pm';
eval "require $x";

trying to eval the code require MyModule.pm is mixing up the two forms and gives an error Bareword "pm" not allowed while "strict subs" in use (which is caught by the eval and placed in $@).

So either just do my $x = 'MyModule'; (and check if eval caught an error, for robustness) or just do:

my $x = 'MyModule.pm';
require $x;

(or eval { require $x } if you wish to trap errors).

That still leaves you your strict error on $test because $test is not exported until runtime and the strict check is at compile time; to solve that, you need to be able to perform your require at compile time:

#!/usr/bin/perl
use 5.014;
use warnings;

BEGIN {
    my $x = 'MyModule';
    my $filename = "$x.pm" =~ s!::!/!gr;
    require $filename;
    $x->import;
}
say $test;

Upvotes: 1

Related Questions