举例说明的是我自己Test::Version
的概要。
use Test::More;
use Test::Version 0.04;
# test blib or lib by default
version_all_ok();
done_testing;
我不必在done_testing();
上添加括号我可以简单地调用它。但是当我试图调用version_all_ok;
时(请注意:首次尝试Dist :: Zilla :: Plugin :: Test :: Version失败)我收到错误。这是为什么?
更新也许我的例子不如我想象的那么好。我得到的实际错误是
Bareword "version_all_ok" not allowed while "strict subs" in use at t/release-test-version.t line 19.
这是完整的代码
#!/usr/bin/perl
BEGIN {
unless ($ENV{RELEASE_TESTING}) {
require Test::More;
Test::More::plan(skip_all => 'these tests are for release candidate testing');
}
}
use 5.006;
use strict;
use warnings;
use Test::More;
eval "use Test::Version";
plan skip_all => "Test::Version required for testing versions"
if $@;
version_all_ok; # of course line 19, and version_all_ok() works here.
done_testing;
以下内容应与从Test::Version 1.0.0
提取的相关摘要一起导出。
use parent 'Exporter';
our @EXPORT = qw( version_all_ok ); ## no critic (Modules::ProhibitAutomaticExportation)
our @EXPORT_OK = qw( version_ok );
答案 0 :(得分:15)
从根本上说,因为Perl需要知道一个裸字意味着一个函数调用,以便将其解析为一个函数调用。 Perl可以通过两种方式学习这个有趣的事实:
您可能已经像函数调用一样修饰了裸字,在&
或->
之前添加或在(...)
之后添加。 Perl会相信你知道你在说什么,并将裸字解析为函数调用,即使它还不知道它将要调用什么函数。
在Perl尝试解析调用之前,您可能已声明了具有该名称的函数。通常,use
- 模块足以确保符号在正确的时间创建;你在Test::Version
做错了,这样在编译测试脚本之后才会导出符号。
在您的代码中,您将use
包装在eval
内,这有效地将其延迟到执行时间。因此,当Perl尝试编译调用并且它会爆炸时,符号version_all_ok
不可用。强制eval
编译时应该足以使符号可用:
BEGIN {
eval "use Test::Version";
plan skip_all => "Test::Version required for testing versions"
if $@;
}
答案 1 :(得分:4)
这个例子显示(显然我认为)您需要的只是预先声明该函数。
#!/usr/bin/env perl
use strict;
use warnings;
sub hi {
print "hi\n";
}
hi; #could be `hi();`
bye(); #could not be `bye;`
sub bye {
print "bye\n";
}
如果您的敏感性要求您在底部定义子例程,但是您希望它们可以在没有parens的情况下调用(就像预先声明的那样),那么您可以使用subs
编译指示:
#!/usr/bin/env perl
use strict;
use warnings;
use subs qw/hi bye/;
hi;
bye;
sub hi {
print "hi\n";
}
sub bye {
print "bye\n";
}
更新:
似乎subs
pragma甚至可以缓解字符串错误带来的问题。您可以在脚本顶部附近尝试use subs 'version_all_ok';
。我的概念证明:
#!/usr/bin/env perl
use strict;
use warnings;
use subs qw/hi bye/;
eval <<'DECLARE';
sub bye {
print "bye\n";
}
DECLARE
hi;
bye;
sub hi {
print "hi\n";
}
答案 2 :(得分:2)
我不能使用Test :: Version 1.0.0或0.04复制它。你有可能没有出口你认为的那样吗?
你能仔细检查并提供失败的完整脚本,错误消息和成功的完整脚本,以及你正在使用的perl版本吗?
更新:好的,你在运行时加载Test :: Version;这意味着在编译时遇到version_all_ok
时,没有这样的子例程。如果不以某种方式修改测试脚本,没有任何办法,例如:
my $has_test_version;
BEGIN { $has_test_version = eval "use Test::Version; 1" }
plan skip_all => "Test::Version required for testing versions" if ! $has_test_version;
答案 3 :(得分:0)
只需要在使用之前声明,仍然使用括号或符号来区分和清晰。
答案 4 :(得分:-1)
如果之前已声明该函数,则允许它,并将其视为列表运算符(警告:它可能会更改运算符优先级!)
答案 5 :(得分:-2)
从Programming Perl开始,第29章功能:
预定义的Perl函数可以在其参数周围使用括号或不使用括号;本章中的语法摘要省略了括号。如果使用括号,那么简单但偶尔会出现令人惊讶的规则是:如果它看起来像一个函数,那么它就是一个函数,所以优先级无关紧要。否则,它是列表运算符或一元运算符,优先级很重要。要小心,因为即使在关键字及其左括号之间放置空格,也不会使它成为一个函数
发现于第677页(由于版权而在Google Books失踪) - 每个Perl程序员都应该有骆驼书。