Pierre Quételart
Pierre Quételart

Reputation: 31

Use of eval to load modules

I'm facing some trouble with Perl and built-in function eval. I have looked around the web but I can't find any answer or sample code.

I'd like to load modules dynamically (I don't know them before the execution time)

$module_name="Auth_Auth_Test";
my $ret1;
ret = eval{
     "use ".$module_name;
     $ret1 = $module_name."::test(".$log.")";
};              
$log->debug ($@) if $@;
$log->debug ("Ret".$ret1);

The return was :

RetAuth_Auth_Test::test(Custom::Log=HASH(0x1194468))

The following method worked for me but I can't load more than one module with same subroutine :

my $use = "use ".$module_name." qw(&test)";
$ret = eval $use;

# Debug for eval
$log->debug ($@) if $@;

$ret = test($log);

Thank you for any help

Upvotes: 3

Views: 2074

Answers (3)

creaktive
creaktive

Reputation: 5210

I strongly advise you to use Class::Load, it is ubiquitous nowadays due to being Moose dependency:

use Class::Load qw(:all);

my $module = 'Web::Spider::' . $module;
try_load_class($module)
    or warn "unable to load '$module'";

And here is an extensive explication on why it is better than Module::Load (despite the late being part of Perl core): http://blog.fox.geek.nz/2010/11/searching-design-spec-for-ultimate.html

TL;DR:

A quirk of how Perl 5.8 functions ( which is now solved in 5.10 ) is that once a module is require'd, as long as that file existed on disk, $INC{ } will be updated to map the module name to the found file name. This doesn't seem to bad, until you see how it behaves with regard to that being called again somewhere else.

Class::Load solves that. Module::Load doesn't.

Upvotes: 3

bvr
bvr

Reputation: 9697

In first snippet, the

"use ".$module_name;

is just evaluated as string. It is because difference between string eval and block eval. See eval documentation for differences between those.

You can use something like this:

use strict; use warnings;

my $module_name = "Auth_Auth_Test";
eval "require $module_name";
if($@) {
    warn "Could not load module: $@\n";
}
my $ret = $module_name->test("params");
print "return $ret\n";

But anyway, daxim's suggestion is sound, you don't probably want to reinvent something already distributed with perl. Module::Load is in core since 5.9.4.

Upvotes: 2

daxim
daxim

Reputation: 39158

Use Module::Load instead.

Upvotes: 6

Related Questions