无法在运行时

时间:2016-12-12 05:40:14

标签: perl import module require

想象一下,我想在运行时加载一个模块。我希望这可以工作

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.165.10.1。)

修改

正如Matt Jacob所述,带括号的调用有效,getcwd()。但是,给定perlsub

  

NAME LIST; #Parentheses如果预先声明/导入,则为可选项。

这意味着导入不起作用,以及为什么遗留问题。

此外,必须根据模块的加载方式使用不同的语法并不好。另外,我不能让非核心模块以这种方式工作,特别是那些语法如List::MoreUtils的模块。

1 个答案:

答案 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 );