在 Perl 中使用裸词有什么陷阱?

What are the pitfalls in using bare words in Perl?

提问人:Ltf4an 提问时间:12/18/2016 最后编辑:Ltf4an 更新时间:12/21/2016 访问量:655

问:

我知道裸字可以用作引用运算符(q//、qq//)、哈希键等的字符串。我个人对此不太兴奋,因为我无法克服应该引用文字字符串的心理期望,就像在 C、C++ 中一样。但是,如果我要采用带引号的字符串和裸词的混合使用,我想确保我不会意外地搬起石头砸自己的脚,因为裸字在运行时无法正确表现。

请排除“use strict”会在编译时将它们捕获为错误的用例。我总是启用“严格”模式,所以我不担心这些情况。

下面是基于提供的答案和注释的代码说明:

#!/usr/bin/perl

use strict;

use constant SIZE => "const_size";

sub size {
    return "getsize";
}

my $href = {
    size => 1,
    getsize => 2,
    const_size => "CONST_SIZE",
    SIZE => "LARGE",
};

print "constant SIZE:", SIZE, "\n";
print "1. \$href->{size}:", $href->{size}, "\n";
print "1a. \$href->{size()}:", $href->{size()}, "\n";
print "2. \$href->{getsize}:", $href->{getsize}, "\n";
print "3. \$href->{SIZE}:", $href->{SIZE}, "\n";
print "3a. \$href->{(SIZE)}:", $href->{(SIZE)}, "\n";

输出:

$ ./bare_word.pl
constant SIZE:const_size
1. $href->{size}:1
1a. $href->{size()}:2
2. $href->{getsize}:2
3. $href->{SIZE}:LARGE
3a. $href->{(SIZE)}:CONST_SIZE

似乎就哈希键而言,裸字在所有情况下都按预期运行。要覆盖该行为,我们需要明确消除歧义。

字符串 perl 引用 bareword

评论

12赞 ThisSuitIsBlackNot 12/18/2016
如果它在里面 或 ,它被引用,所以你不能称它为赤裸裸的词。( 完全等同于单引号,完全等同于双引号)。qqqqqq
0赞 Ltf4an 12/18/2016
@ThisSuitIsBlackNot,我称它为q//中的裸词,因为它们的外观。是的,我问的是运行时错误。
1赞 zdim 12/18/2016
另一个例子出现在 where-are-perl-constants-replaced-by-their-values 中。
3赞 Dave Sherohman 12/18/2016
所以。。。呃......在您看来,如果不引用其内容,引用操作员会做什么?
3赞 Borodin 12/18/2016
你的评论“我称它为q//中的裸露词,因为他们的外表”让我担心。你能解释一下你对它们的外观是什么意思吗,以及它与和的外观有何不同?如果你说了,我可以开始理解,但即使这样也是非常不同的事情。我认为你以某种方式误导了自己,我无法遵循你的思路。''""qw//

答:

5赞 ThisSuitIsBlackNot 12/18/2016 #1

是的,你可以因为没有正确引用东西而搬起石头砸自己的脚:

$ perl -MData::Dumper -e'
    my %h;
    $h{"foo-bar"} = 1;
    print Dumper \%h
'
$VAR1 = {
          'foo-bar' => 1
        };

$ perl -MData::Dumper -e'
    my %h;
    $h{foo-bar} = 1;
    print Dumper \%h
'
$VAR1 = {
          '0' => 1  # oops!
        };

但是,严格模式会将其从未捕获的逻辑错误转换为语法错误:

$ perl -Mstrict -MData::Dumper -e'
    my %h; 
    $h{foo-bar} = 1; 
    print Dumper \%h
'
Bareword "foo" not allowed while "strict subs" in use at -e line 1.
Bareword "bar" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

...除非:

$ perl -Mstrict -MData::Dumper -e'
    sub foo { 1 }
    sub bar { 1 }

    my %h;
    $h{foo-bar} = 1;
    print Dumper \%h
'
Ambiguous use of -bar resolved as -&bar() at -e line 1.
$VAR1 = {
          '1' => 1  # oops!
        };

这个故事的寓意是什么?Always 和 always 引号不是标识符的哈希键(标识符仅包含字母、数字和下划线,第一个字符不能是数字)。use strict;

评论

0赞 Ltf4an 12/18/2016
当我运行上面的代码时,我没有得到“模棱两可地使用 -bar”行。我的 Perl 版本是:这是为 cygwin-thread-multi 构建的 perl 5 版本 22 subversion 2 (v5.22.2)。您的示例 (%h{foo-bar}) 是我正在寻找的用例。还有其他情况吗?
1赞 ThisSuitIsBlackNot 12/18/2016
@Ltf4an 该警告是虚假的,因此在 5.22.0 中删除了它。不过,这不是重要的部分。
1赞 ThisSuitIsBlackNot 12/18/2016
@Ltf4an 是的,胖逗号运算符也有类似的陷阱:perl -Mstrict -MData::Dumper -e'sub foo { 1 } sub bar { 1 } my %h = ( foo.bar => 1 ); print Dumper \%h'
0赞 Ltf4an 12/19/2016
根据您上面的评论,我已更新描述以使用“陷阱”一词。我认为它更能描述我正在寻找的东西。
0赞 ikegami 12/19/2016
你上一次写是什么时候?唯一真正的问题是.sub foo.bar { ... }$hash{CONSTANT}
6赞 ikegami 12/19/2016 #2

请排除“use strict”会在编译时将它们捕获为错误的用例。

use strict;完全防止使用赤词。允许赤裸裸的单词允许错别字非常无声和/或微妙地失败。

该文档声称,在未来的Perl版本中,小写的裸字可能会被误解为函数调用,但事实并非如此。需要启用新功能,例如 .say


也就是说,我认为您实际上是想谈论自动引号的哈希键。存在混淆的可能性,因为人们可能会写到期望它等于 .但是,不仅(与此相反)首先称呼潜艇是一种奇怪的方式,而且没有人愿意首先编写。(肯定需要一个论据。$hash{foo}$hash{foo()}foofoo()$hash{foo()}

唯一防止代码被误解的可能性无限小的是常量被用作哈希键的可能性。 会失败。需要使用 、 或其他形式的消歧义。$hash{CONSTANT}$hash{(CONSTANT)}$hash{+CONSTANT}