有人想在 use
中使用数组变量代替数组(列表)文字。函数语句,如:
my @list = qw(foo zoo);
use Module @list;
代替
use Module qw(foo zoo);
所以她写道,例如:
my @consts = qw(PF_INET PF_INET6);
use Socket @consts;
printf "%d, %d\n", PF_INET, PF_INET6;
这似乎按预期工作:
2, 10
然后她正在使用其他模块进行操作,例如
Time::HiRes
.代替use Time::HiRes qw(CLOCK_REALTIME CLOCK_MONOTONIC);
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;
0, 1
她这样做:
my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
use Time::HiRes @consts;
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;
0, 0
它突然不起作用,就像它与
Socket
一样模块!这里正在发生一些不好的事情。
(.. 这是在非严格环境中。如果她使用
use strict
,她甚至会得到一个错误。另一方面,在她的第一个看似有效的示例中,她根本没有得到任何提示 - 即使她有 use strict; use warnings; use diagnostics
那里。)现在她想探索这种奇怪的行为。尝试导入一个空列表:
my @consts = ();
use Socket @consts;
printf "%d, %d\n", PF_INET, PF_INET6;
2, 10
令人惊讶的效果也很好,虽然它可能不应该,比如:
use Socket ();
printf "%d, %d\n", PF_INET, PF_INET6;
0, 0
然后她稍微深入研究了这些模块并意识到这两个模块之间的区别在于这些常量是/不是
@EXPORT
。分别编辑。她的结论是
use Module @list
没有按她的预期工作。对此最好的解释是什么?她做错了什么 - 在
use
中使用预定义数组的正确方法是什么?陈述?
最佳答案
这与执行代码的时间有关。 use
在编译时执行,而 my @list
仅在运行时执行。所以数组在模块加载点不存在。
模块Socket exports PF_INET
和 PF_INET6
默认情况下,所以不管你把它放在 use
线。但是时间::HiRes does not export stuff默认情况下。
你得到的错误 strict
是:
Bareword "CLOCK_REALTIME" not allowed while "strict subs" in use ...
这告诉我们 Perl 不知道
CLOCK_REALTIME
是一个子,这是真的,因为当我们这样做时它没有被加载:my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
use Time::HiRes @consts;
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;
What
use
does是 require
模块和import
编译时的参数列表。所以它是一样的:BEGIN {
require foo;
foo->import();
}
知道了这一点,我们可以自己做:
use strict; use warnings;
BEGIN {
my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
require Time::HiRes;
Time::HiRes->import(@consts);
}
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;
__END__
0, 1
像这样它会起作用,因为数组
@const
在同一范围内定义,并且在 Perl 解释器执行时已经可用。由于作用域,只需添加
BEGIN
挡在前面使用会不是 工作。BEGIN {
my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
}
use Time::HiRes (@consts);
您可以通过在
BEGIN
之外声明变量来解决此问题。堵塞。这样它将在下一个 BEGIN
中可用 block 的范围,并且该值已经设置,因为 BEGIN
blocks are executed at compile time in FIFO order .my @consts;
BEGIN {
@consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
}
use Time::HiRes (@consts);
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;
__END__
0, 1
回顾一下:
use strict
,你不容易找到问题BEGIN
挡在 use
前面并放置 my
BEGIN
之外的声明,它有效require
而不是 use
和 import
你自己,你也可以传递一个数组关于Perl:使用模块@list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20396722/