想象一下,我想在运行时加载一个模块。我希望这可以工作
use warnings;
use strict;
eval {
require Cwd;
Cwd->import;
};
if ($@) { die "Can't load Cwd: $@" }
say "Dir: ", getcwd;
但不是,Bareword "getcwd" not allowed ...
。
默认情况下Cwd导出getcwd
。我尝试将函数名称提供给import
,并尝试使用其他函数。
它使用全名say Cwd::getcwd
,所以我认为它不是导入。
这适用于我尝试的其他一些核心模块,例如
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";
添加了注释显然,带括号的函数调用为编译器提供了线索。但是,在我看来问题仍然存在,请在最后看到 EDIT 。此外,上述模块中的first BLOCK LIST
函数不起作用。
但是, 不适用于我尝试的一些(已建立的)非核心模块。更糟糕和更令人困惑的是,即使使用完全限定的名称,它也不起作用。
我可以想象,如果在运行时使用require
,则在编译时不知道所使用的符号(函数),但它适用于(其他)核心模块。我认为这是在运行时加载的标准方法。
如果我在动态加载时需要使用全名,那么很好,但是它的不一致是什么?以及如何做我在运行时加载(和使用)非核心模块?
我也试过了Module::Load::Conditional
,但它没有用。
我缺少什么,以及如何在运行时加载模块? (尝试使用5.16
和5.10.1
。)
修改的
正如Matt Jacob所述,带括号的调用有效,getcwd()
。但是,给定perlsub
NAME LIST;
#Parentheses如果预先声明/导入,则为可选项。
这意味着导入不起作用,以及为什么遗留问题。
此外,必须根据模块的加载方式使用不同的语法并不好。另外,我不能让非核心模块以这种方式工作,特别是那些语法如List::MoreUtils的模块。
答案 0 :(得分:5)
首先,这与核心模块和非核心模块无关。当解析器必须猜测特定标记是否是函数调用时,就会发生这种情况。
eval {
require Cwd;
Cwd->import;
};
if ($@) { die "Can't load Cwd: $@" }
say "Dir: ", getcwd;
在编译时,getcwd
符号表中没有main::
。没有任何提示表明它是一个函数(getcwd()
或&getcwd
),解析器无法知道,strict
会抱怨。
eval {
require List::Util;
List::Util->import('max');
};
if ($@) { die "Can't load List::Util: $@" }
my $max = max (1, 14, 3, 26, 2);
在编译时,max
符号表中没有main::
。但是,由于您使用括号调用max
,解析器可以猜测它是稍后定义的函数,因此strict
不会抱怨。
在这两种情况下,strict
检查都会在import
被调用之前发生。
List :: MoreUtils很特别,因为函数使用原型。如果函数定义在编译时不可见,则忽略原型。因此,您不仅必须为解析器提供一个您正在调用函数的提示,还必须以不同方式调用它,因为原型将被忽略:
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 );