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
然后,她正在使用其他模块,例如时间::高分辨率.代替
use Time::HiRes qw(CLOCK_REALTIME CLOCK_MONOTONIC); printf "%d,CLOCK_REALTIME,CLOCK_MONOTONIC;
0,1
她这样做:
my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC); use Time::HiRes @consts; printf "%d,0它突然不起作用,就像它与Socket模块一起工作!
这里发生了一件坏事.(..它是在非严格的环境中.如果她使用严格,她甚至会出错.另一方面,她在她的第一个看似有效的例子中没有任何暗示 – 即使她严格使用;使用警告;在那里使用诊断.)
现在她想探索这种奇怪的行为.尝试导入空列表:
my @consts = (); use Socket @consts; printf "%d,PF_INET6;2,10
令人惊讶地工作,虽然它可能不应该,如:
use Socket (); printf "%d,PF_INET6;0,0
然后她稍微深入了解这些模块,并意识到两个模块之间的区别在于这些常量分别是@EXPORTed.
她的结论是使用Module @list不能像她期望的那样工作.
对此最好的解释是什么?她做错了什么 – 在use语句中使用预定义数组的正确方法是什么?
解决方法
模块Socket exports PF_INET和PF_INET6默认情况下,因此如果将其放入使用行中则无关紧要.但是Time :: HiRes does not export stuff默认情况下.
你严格得到的错误是:
Bareword “CLOCK_REALTIME” not allowed while “strict subs” in use …
这告诉我们Perl不知道CLOCK_REALTIME是一个sub,这是真的,因为当我们这样做时它没有被加载:
my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC); use Time::HiRes @consts; printf "%d,CLOCK_MONOTONIC;
What use
does需要模块并在编译时导入参数的LIST.所以它是一样的:
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,CLOCK_MONOTONIC; __END__ 0,1
像这样它可以工作,因为数组@const在相同的范围内定义,并且在Perl解释器执行它时已经可用.
由于范围界定,只需在使用前添加BEGIN块就行不通.
BEGIN { my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC); } use Time::HiRes (@consts);
您可以通过在BEGIN块之外声明变量来解决问题.这样它将在下一个BEGIN块的范围内可用,并且因为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,1
所以回顾一下:
>这是因为两件事:范围和执行顺序
>传递数组的事实不是问题 – 数组将是传递的part of the LIST>如果你不使用严格,你不能轻易找到问题>如果你在使用前添加一个BEGIN块并将我的声明放在BEGIN之外,它就可以了>如果您采用require而不是使用并自行导入,您也可以传递数组