Perl 如何使用“导入常量”;使用“严格的”;,避免";Can';不要用空话。。。作为数组引用";
我在一个文件中有一个模块,它导出一个常量,该常量是数组引用。我可以在其定义模块中使用该常量,但在导入后无法使用它。当mod.pl第28行使用“strict refs”时,错误消息显示Perl 如何使用“导入常量”;使用“严格的”;,避免";Can';不要用空话。。。作为数组引用";,perl,import,module,reference,constants,Perl,Import,Module,Reference,Constants,我在一个文件中有一个模块,它导出一个常量,该常量是数组引用。我可以在其定义模块中使用该常量,但在导入后无法使用它。当mod.pl第28行使用“strict refs”时,错误消息显示不能将bareword(“AR”)用作数组引用。 考虑以下演示代码: #!/usr/bin/perl require 5.018_000; use warnings; use strict; package Test; use warnings; use strict; BEGIN { require
不能将bareword(“AR”)用作数组引用。
考虑以下演示代码:
#!/usr/bin/perl
require 5.018_000;
use warnings;
use strict;
package Test;
use warnings;
use strict;
BEGIN {
require Exporter;
our $VERSION = 1.00; # for version checking
# Inherit from Exporter to export functions and variables
our @ISA = qw(Exporter);
our @EXPORT = qw(); # exported by default
our @EXPORT_OK = qw(AR); # can be optionally exported
}
use constant AR => [1,2,3];
print AR->[1], "\n";
1;
package main;
Test->import(qw(AR));
print AR->[1], "\n";
#Can't use bareword ("AR") as an ARRAY ref while "strict refs" in use at mod.pl line 28.
如何修复它?编译时会解析
print AR->[1]
语句,但常量AR
直到运行时才会导入main
命名空间
修复方法是确保编译时将AR
导入main
BEGIN { Test->import( qw(AR) ) }
还有一些运行时解决方法
print &AR->[1], "\n";
print AR()->[1], "\n";
我变了
BEGIN {
require Exporter;
our $VERSION = 1.00; # for version checking
# Inherit from Exporter to export functions and variables
our @ISA = qw(Exporter);
our @EXPORT = qw(); # exported by default
our @EXPORT_OK = qw(AR); # can be optionally exported
}
到
您的代码现在可以工作了
我怀疑在设置
@EXPORT\u OK
变量之前必须运行Exporter中的某些代码在编译对常量的引用之前,需要执行import
您可以使用另一个BEGIN
块来完成此操作,但这意味着我们现在有两个hack。我建议采用以下方法,而不是同时对模块的用户和模块本身进行弗兰肯斯坦分析。它尽可能使内联包看起来像一个真正的模块
该方法包括以下内容:
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
1;
#!/usr/bin/perl
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
#!/usr/bin/perl
BEGIN {
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
$INC{__PACKAGE__ .'.pm'} = 1; # Tell Perl the module is already loaded.
}
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
BEGIN
块中1代码>与$INC{“Foo/Bar.pm”}=1代码>(用于Foo::Bar
)
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
1;
#!/usr/bin/perl
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
#!/usr/bin/perl
BEGIN {
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
$INC{__PACKAGE__ .'.pm'} = 1; # Tell Perl the module is already loaded.
}
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
如果您的脚本如下所示:
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
1;
#!/usr/bin/perl
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
#!/usr/bin/perl
BEGIN {
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
$INC{__PACKAGE__ .'.pm'} = 1; # Tell Perl the module is already loaded.
}
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
您可以使用以下选项:
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
1;
#!/usr/bin/perl
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
#!/usr/bin/perl
BEGIN {
package Test;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our @EXPORT_OK = qw(AR);
use constant AR => [1,2,3];
$INC{__PACKAGE__ .'.pm'} = 1; # Tell Perl the module is already loaded.
}
use 5.018;
use warnings;
use Test qw( AR );
say AR->[1];
如你所见,我做了一些清理。具体来说,
- 如果您需要5.18,不妨启用它提供的语言功能。这是通过替换
要求的5.018来实现的代码>使用
使用5.018代码>
- 我们不需要使用
严格代码>明确,因为
使用5.012代码>和更高级别启用限制
- 我们可以使用
,因为说
使用5.010代码>启用它
- 我们不需要使用
- 测试不是导出器,因此它不应从导出器继承。在过去的15-20年中,Exporter提供了比您使用的更好的界面
- 如果不需要,则无需创建或初始化
@EXPORT
- 无需在
和@ISA
的初始化周围设置@EXPORT\u OK
块BEGIN
未定义的子例程&main::AR
错误消息。奇怪的是,我使用的是Perl 5.20.2,它显然失败了,这就是我添加答案的原因。我想有人修复了我们两个版本之间的一个bug。所有三个解决方案在5.20中都可以正常工作。事实上,如果您删除require5.018_000,它们在5.6到现在(5.28)的所有版本中都可以正常工作
@ikegami:想对要求5.018_000
发表评论吗?我认为它支持Perl5.18的语言特性(这是我一直使用的版本),它只是确保解释器的版本是5.18+。对于您的程序来说完全不需要这个更改。@zdim:这正是man perlmod(1)
中给出的代码。啊,您是对的。。。有人应该编辑它,以免混淆人们。毫无疑问,这是一个具有实际意义的讨论(20年前?),但这不是我们建立模块的方式。请参阅以获取更简单、更清晰的信息(样板)。当然还有很多帖子,从池上的回答开始here@zdim我打开了一个带有补丁的perlbug:@Grinnz好极了,谢谢。我再次回顾了这一部分,它实际上是作为一个模块的简单实用的概述提供的(可以这么说)。它真的应该被修复。所以真正的诀窍是$INC{“Test.pm”}=1
并且使用一个普通的使用Test
?请问我的代码有什么不适用?另外,是否可以使“test.pm”
独立于实际使用的文件名?不,我清楚地列出了“技巧”的两个步骤,这只是其中之一%INC
in中的键的名称基于包的名称(即基于模块世界的名称),而不是脚本的名称。@U.Windl您的代码没有按预期工作的原因特别是因为您在使用模块的同一文件中以及在编译时定义了模块(要导入符号以供以后使用时)因此,模块尚未运行,您的import
调用也未运行。如果将模块保存在单独的文件中,一切都将正常工作,因为模块将在脚本的编译阶段通过use
语句编译、运行和导入-另一方面,您的手册import
发生在runtime、 @Grinnz:我在理解上仍然有问题:我以为使用常量…
是在编译时计算的。我知道导出程序的东西和$INC{“Test.pm”}=1
必须在开始
块中,但为什么要在其余的块中呢?将整个模块包装在开始块中会更短、更简单、更干净。这也更接近加载模块的正常方式。是的,您可以使用普通块而不是开始块,并在其中使用多个开始块(如图所示),但这要长得多,复杂得多,容易出错,而且杂乱无章。它还需要更多的缩进和键入。根本没有理由这样做。