首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl:使用模块@列表

Perl:使用模块@列表
EN

Stack Overflow用户
提问于 2013-12-05 09:55:15
回答 1查看 706关注 0票数 7

有人想在use函数语句中使用数组变量来代替数组(列表)文字,如下所示:

代码语言:javascript
复制
my @list = qw(foo zoo);
use Module @list;

而不是

代码语言:javascript
复制
use Module qw(foo zoo);

因此,她写道:

代码语言:javascript
复制
my @consts = qw(PF_INET PF_INET6);
use Socket @consts;
printf "%d, %d\n", PF_INET, PF_INET6;

它似乎像预期的那样起作用:

2、10

然后,她正在使用其他模块,例如Time::HiRes。而不是

代码语言:javascript
复制
use Time::HiRes qw(CLOCK_REALTIME CLOCK_MONOTONIC);
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;

0,1

她这样做了:

代码语言:javascript
复制
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

现在她想探索这种奇怪的行为。尝试导入空列表:

代码语言:javascript
复制
my @consts = ();
use Socket @consts;
printf "%d, %d\n", PF_INET, PF_INET6;

2、10

令人惊讶的是,它也起作用,而它可能不应该,比如:

代码语言:javascript
复制
use Socket ();
printf "%d, %d\n", PF_INET, PF_INET6;

0,0

然后,她稍微深入这些模块,并意识到,这两个模块之间的区别是,这些常量分别是/不是@EXPORT编辑的。

她的结论是use Module @list不像她期望的那样起作用。

对此最好的解释是什么?她做错了什么?在use语句中使用预定义数组的正确方法是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-05 10:31:16

这与执行代码的时间有关。use在编译时执行,而my @list只在运行时执行。因此,数组不存在加载模块的点。

默认情况下,模块插座出口 PF_INETPF_INET6,所以如果将它放在use行中并不重要。但是时间::默认情况下雇用不出口东西

您在strict中遇到的错误是:

在使用“严格的潜艇”时不允许使用"CLOCK_REALTIME“一词。

这告诉我们Perl不知道CLOCK_REALTIME是一个子程序,这是正确的,因为我们这样做时没有加载它:

代码语言:javascript
复制
my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
use Time::HiRes @consts;
printf "%d, %d\n", CLOCK_REALTIME, CLOCK_MONOTONIC;

有吗?require模块,import是编译时的参数列表。所以这和:

代码语言:javascript
复制
BEGIN {
  require foo;
  foo->import();
}

知道了这一点,我们自己就能做到:

代码语言:javascript
复制
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块将使而不是工作。

代码语言:javascript
复制
BEGIN {
  my @consts = qw(CLOCK_REALTIME CLOCK_MONOTONIC);
}

use Time::HiRes (@consts);

您可以通过在BEGIN块之外声明变量来解决这个问题。这样,它将在下一个BEGIN块的作用域中可用,并且该值已经被设置,因为块以FIFO顺序在编译时执行。

代码语言:javascript
复制
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而不是useimport,您也可以传递一个数组
票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20396722

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档