38

在 Perl 中使用哈希时引用键是个好主意吗?

我正在处理一个非常大的遗留 Perl 代码库,并尝试采用 Damian Conway 在Perl Best Practices中提出的许多最佳实践。我知道最佳实践对于程序员来说总是一个敏感的话题,但希望我能在这个问题上得到一些好的答案,而不会引发一场激烈的战争。我也知道这可能是很多人不会争论的事情,因为它是一个小问题,但我正在努力获得一份可靠的指南列表,以便在我通过这个代码库工作时遵循。

Damian Conway 的 Perl Best Practices 书中,有一个例子展示了对齐如何帮助一段代码的易读性,但它没有提到(在书中我能找到的任何地方)关于引用哈希键的任何内容。

$ident{ name   } = standardize_name($name);
$ident{ age    } = time - $birth_date;
$ident{ status } = 'active';

用引号来强调你没有使用裸词不是更好吗?

$ident{ 'name'   } = standardize_name($name);
$ident{ 'age'    } = time - $birth_date;
$ident{ 'status' } = 'active';
4

13 回答 13

36

没有引号更好。它在 {} 中,因此很明显您没有使用裸词,而且它更易于阅读和输入(少两个符号)。当然,所有这些都取决于程序员。

于 2008-12-30T21:30:56.213 回答
33

指定常量字符串哈希键时,应始终使用(单)引号。例如, $hash{'key'} 这是最好的选择,因为它不需要考虑这个问题并导致格式一致。如果您有时省略引号,则必须记住在您的密钥包含内部连字符、空格或其他特殊字符时添加它们。在这些情况下您必须使用引号,导致格式不一致(有时不加引号,有时加引号)。带引号的键也更有可能被您的编辑器语法高亮。

这是一个示例,其中使用“有时引用,其他时间不引用”约定会给您带来麻烦:

$settings{unlink-devices} = 1; # I saved two characters!

这将在 下编译得很好use strict,但在运行时不会完全符合您的期望。哈希键是字符串。字符串应根据其内容进行适当引用:单引号表示文字字符串,双引号表示允许变量插值。引用您的哈希键。这是最安全的约定,也是最容易理解和遵循的。

于 2008-12-31T02:11:27.473 回答
12

我从不单引号哈希键。我知道 {} 基本上像引号一样工作,除了在特殊情况下(a + 和双引号)。我的编辑也知道这一点,并给了我一些基于颜色的提示,以确保我做了我想要的。

在我看来,到处使用单引号就像不了解 Perl 的人所犯的一种“防御性”做法。节省一些键盘磨损并学习 Perl :)

随着咆哮的结束,我发布此评论的真正原因......其他评论似乎错过了+“取消引用”一个裸词的事实。这意味着你可以写:

sub foo {
    $hash{+shift} = 42;
}

或者:

use constant foo => 'OH HAI';
$hash{+foo} = 'I AM A LOLCAT';

所以很明显,这+shift意味着“调用 shift 函数”和shift“字符串 'shift'”。

我还要指出,cperl-mode 正确地突出了所有各种情况。如果没有,请在 IRC 上 ping 我,我会修复它 :)

(哦,还有一件事。我确实在 Moose 中引用了属性名称,如has 'foo' => ....我的代码。也许我很快就会停止这样做。)

于 2009-01-11T01:35:34.917 回答
10

无引号的哈希键得到了 Larry Wall 的语法级别的关注,以确保它们没有理由成为最佳实践。不要为引号而汗流浃背。

(顺便说一句,数组键上的引号PHP 中的最佳实践,如果不使用它们可能会产生严重后果,更不用说大量的 E_WARNING。在 Perl 中可以!= 在 PHP 中可以。)

于 2008-12-30T21:36:16.437 回答
6

我认为这没有最佳实践。我个人在哈希键中使用它们,如下所示:

$ident{'name'} = standardize_name($name);

但不要在箭头运算符的左侧使用它们:

$ident = {name => standardize_name($name)};

不要问我为什么,这就是我做的方式:)

我认为你能做的最重要的事情就是永远,永远,永远:

use strict;
use warnings; 

这样编译器就会为你捕捉到任何语义错误,让你不太可能打错东西,无论你决定采用哪种方式。

第二个最重要的事情是保持一致。

于 2008-12-31T00:44:25.670 回答
5

我不带引号,只是因为打字、阅读和担心的次数更少。我有一个不会被自动引用的密钥的时间很少而且相差很远,因此不值得所有额外的工作和混乱。也许我对哈希键的选择已经改变以适应我的风格,这也是一样的。完全避免边缘情况。

"这与我默认使用的原因相同。对我来说,在字符串中间插入一个变量比使用一个我不想插值的字符更常见。也就是说,我写得'Hello, my name is $name'"You owe me $1000".

于 2009-01-03T21:50:14.773 回答
4

至少,在不太完美的编辑器中,引用可以防止语法高亮保留字。查看:

$i{keys} = $a;
$i{values} = [1,2];
...
于 2008-12-31T00:00:11.560 回答
3

跟着报价走!它们在视觉上分解了语法,更多的编辑器将在语法高亮中支持它们(嘿,甚至 Stack Overflow 也在高亮引用版本)。我还争辩说,当编辑检查您是否结束了报价时,您会更快地注意到拼写错误。

于 2008-12-30T23:55:44.410 回答
3

我更喜欢不带引号,除非我想要一些字符串插值。然后我使用双引号。我把它比作文字数字。Perl 确实允许您执行以下操作:

$achoo['1']  = 'kleenex';
$achoo['14'] = 'hankies';

但没有人这样做。而且它对清晰度没有帮助,仅仅是因为我们添加了另外两个字符来输入。就像有时我们特别希望数组中的插槽 #3 一样,有时我们希望PATH%ENV. 就我而言,单引号不会增加清晰度。

Perl 解析代码的方式使得不可能在哈希索引中使用其他类型的“裸词”。

尝试

$myhash{shift}

而且您只会将项目存储在密钥下的哈希中'shift',您必须这样做

$myhash{shift()}

为了指定您希望第一个参数来索引您的哈希。

此外,我使用jEdit,这是唯一的可视化编辑器(除了 emacs 之外,我见过),它可以让完全控制突出显示。所以这对我来说是双重清楚的。任何看起来像前者的东西都会得到 KEYWORD3 ($myhash) + SYMBOL ({) + LITERAL2 (shift) + SYMBOL (}),如果在结束花括号之前有一个括号,它会得到 KEYWORD3 + SYMBOL + KEYWORD1 + SYMBOL (()})。另外,我也可能会像这样格式化它:

$myhash{ shift() }
于 2008-12-31T04:22:56.897 回答
2

使用引号更好,因为它允许您使用裸字中不允许的特殊字符。通过使用引号,我可以在哈希键中使用我母语的特殊字符。

于 2008-12-30T22:50:29.237 回答
2

您也可以在键前加上“ -”(减号),但请注意,这会将“ -”附加到键的开头。从我的一些代码:

$args{-title} ||= "Intrig";

我也使用单引号、双引号和无引号的方式。都在同一个程序中:-)

于 2008-12-31T05:08:45.103 回答
2

我自己也想知道这一点,尤其是当我发现我犯了一些错误时:

 use constant CONSTANT => 'something';
 ...
 my %hash = ()
 $hash{CONSTANT}          = 'whoops!';  # Not what I intended
 $hash{word-with-hyphens} = 'whoops!';  # wrong again 

如果至少有一个文字键需要引号,我现在倾向于在每个哈希的基础上普遍应用引号;并使用带常量的括号:

 $hash{CONSTANT()} = 'ugly, but what can you do?';
于 2009-01-01T10:23:08.980 回答
0

我一直在不带引号的情况下使用它们,但我会重复使用严格和警告,因为它们会找出大多数常见错误。

于 2008-12-31T06:43:55.863 回答