【问题标题】:What are the pitfalls in using bare words in Perl?在 Perl 中使用裸词有哪些陷阱?
【发布时间】:2017-05-03 11:16:03
【问题描述】:

我知道在引用运算符(q//、qq//)、哈希键等中可以将裸词用作字符串。我个人对此不太感兴趣,因为我无法克服心理预期应该引用文字字符串,如在 C、C++ 中。但是,如果我要混合使用带引号的字符串和裸词,我想确保我不会意外地在裸词在运行时无法正常运行的情况下误伤自己。

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

下面是根据提供的答案和cmets的代码说明:

#!/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

似乎对于散列键,裸词在所有情况下的行为都符合预期。要覆盖该行为,我们需要明确消除歧义。

【问题讨论】:

  • 如果它在qqq 内,它引用,所以你不能称之为裸词。 (q 完全等同于单引号,qq 完全等同于双引号)。
  • @ThisSuitIsBlackNot,由于它们的外观,我在 q// 中将其称为裸词。是的,我问的是运行时错误。
  • 所以...嗯...在您的脑海中,如果不是 quote 它的内容,quoting 运算符会做什么?
  • 您的评论“我在q// 中称其为裸词,因为它们的外观” 让我很担心。你能解释一下你对它们的外观的含义,以及它与''"" 的外观有何不同?如果您说qw//,我可以开始理解,但即使那是非常不同的东西。我认为你以某种方式误导了自己,我无法遵循你的思路。

标签: string perl quotes bareword


【解决方案1】:

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

use strict; 完全禁止使用barewords。允许使用裸词可以让拼写错误非常安静和/或巧妙地失败。

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


也就是说,我认为您实际上是在谈论自动引用的哈希键。可能会造成混淆,因为人们可能会写$hash{foo},期望它等同于$hash{foo()}。但不仅foo(相对于foo())是一种奇怪的调用sub 的方式,而且没有人会想首先写$hash{foo()}。 (肯定需要论证。)

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

【讨论】:

    【解决方案2】:

    是的,如果没有正确引用的话,你可能会自取其辱:

    $ 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!
            };
    

    故事的寓意?总是use strict;,并且总是引用不是identifiers 的哈希键(标识符只包含字母、数字和下划线,并且第一个字符不能是数字)。

    【讨论】:

    • 当我运行上面的代码时,我没有得到“Ambiguous use of -bar”的行。我的 Perl 的版本是:这是为 cygwin-thread-multi 构建的 perl 5, version 22, subversion 2 (v5.22.2)。您的 (%h{foo-bar}) 示例是我正在寻找的用例。还有其他情况吗?
    • @Ltf4an 警告是虚假的,所以它是removed in 5.22.0。不过,这不是重要的部分。
    • @Ltf4an 是的,胖逗号运算符也有类似的陷阱:perl -Mstrict -MData::Dumper -e'sub foo { 1 } sub bar { 1 } my %h = ( foo.bar => 1 ); print Dumper \%h'
    • 根据您上面的评论,我已更新描述以使用“陷阱”一词。我认为它更能描述我正在寻找的内容。
    • 你最后一次写sub foo.bar { ... }是什么时候?唯一真正的问题是$hash{CONSTANT}
    猜你喜欢
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 2015-07-07
    • 2012-06-05
    • 2012-02-03
    • 2016-08-19
    相关资源
    最近更新 更多