无法在运行时加载“Cwd”(以及其他非核心模块)

Cannot load `Cwd` (and other, non-core, modules) at runtime

假设我想在运行时加载一个模块。我希望这能奏效

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, a call with parenthesis works, getcwd(). However, given perlsub

所述

NAME LIST; # Parentheses optional if predeclared/imported.

这意味着导入没有起作用,为什么问题仍然存在。

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

的模块

首先,这与核心模块与非核心模块无关。当解析器必须猜测特定标记是否是函数调用时,就会发生这种情况。


eval {
    require Cwd; 
    Cwd->import;
};
if ($@) { die "Can't load Cwd: $@" }

say "Dir: ", getcwd;

在编译时,main::符号table中没有getcwd。没有任何提示表明它是一个函数(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);

在编译时,main::符号table中没有max。但是,由于您用括号调用 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 );