Imagine I want to load a module at runtime. I expected this to work
use warnings;
use strict;
eval {
require Cwd;
Cwd->import;
};
if ($@) { die "Can't load Cwd: $@" }
say "Dir: ", getcwd;
but it doesn't, per Bareword "getcwd" not allowed ...
.
The Cwd exports getcwd
by default. I tried giving the function name(s) to import
and I tried with its other functions.
It works with the full name, say Cwd::getcwd
, so I'd think that it isn't importing.
This works as attempted for a few other core modules that I tried, for example
use warnings;
use strict;
eval {
require List::Util;
List::Util->import('max');
};
if ($@) { die "Can't load List::Util: $@" }
my $max = max (1, 14, 3, 26, 2);
print "Max is $max\n";
NOTE added Apparently, function calls with parenthesis give a clue to the compiler. However, in my opinion the question remains, please see EDIT at the end. In addition, a function like first BLOCK LIST
from the module above does not work.
However, it does not work for a few (well established) non-core modules that I tried. Worse and more confusingly, it does not work even with the fully qualified names.
I can imagine that the symbol (function) used is not known at compile time if require
is used at runtime, but it works for (other) core modules. I thought that this was a standard way to load at runtime.
If I need to use full names when loading dynamically then fine, but what is it with the inconsistency? And how do I load (and use) non-core modules at runtime?
I also tried with Module::Load::Conditional
and it did not work.
What am I missing, and how does one load modules at runtime? (Tried with 5.16
and 5.10.1
.)
EDIT
As noted by Matt Jacob, a call with parenthesis works, getcwd()
. However, given perlsub
NAME LIST;
# Parentheses optional if predeclared/imported.
this implies that the import didn't work and the question of why remains.
Besides, having to use varied syntax based on how the module is loaded is not good. Also, I cannot get non-core modules to work this way, specially the ones with syntax like List::MoreUtils has.
First, this has nothing to do with core vs. non-core modules. It happens when the parser has to guess whether a particular token is a function call.
eval {
require Cwd;
Cwd->import;
};
if ($@) { die "Can't load Cwd: $@" }
say "Dir: ", getcwd;
At compile time, there is no getcwd
in the main::
symbol table. Without any hints to indicate that it's a function (getcwd()
or &getcwd
), the parser has no way to know, and strict
complains.
eval {
require List::Util;
List::Util->import('max');
};
if ($@) { die "Can't load List::Util: $@" }
my $max = max (1, 14, 3, 26, 2);
At compile time, there is no max
in the main::
symbol table. However, since you call max
with parentheses, the parser can guess that it's a function that will be defined later, so strict
doesn't complain.
In both cases, the strict
check happens before import
is ever called.
List::MoreUtils is special because the functions use prototypes. Prototypes are ignored if the function definition is not visible at compile time. So, not only do you have to give the parser a hint that you're calling a function, you also have to call it differently since the prototype will be ignored:
use strict;
use warnings 'all';
use 5.010;
eval {
require List::MoreUtils;
List::MoreUtils->import('any')
};
die "Can't load List::MoreUtils: $@" if $@;
say 'found' if any( sub { $_ > 5 }, 1..9 );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With