在Perl中,我应该使用$hash{"string"}还是$hash{string}?

9
在Perl中,哪种风格更好呢?
$hash{"string"} or $hash{string}?

无论如何,它们的功能都是相同的吗?

1
在 Perl 中,违反样式规则就是良好的风格! - Artelius
2
第一个版本在 Stack Overflow 上粘贴代码时效果更好。 - Brad Gilbert
4
你为什么在意?真的,你的代码里肯定有更重要的事情需要关注。只要别人的东西能正常运行,我不在乎他们使用哪一个。 - brian d foy
我同意Brian的观点。为什么要在意呢?如果之前已经有人问过同样的问题,为什么还要再问一遍呢?https://dev59.com/2nRC5IYBdhLWcg3wJNYN - innaM
12
@brian和Manni--刚学Perl的人可能会被所有不同的样式弄得很困惑,Jessica可能正是这样的人。她在学习该语言时可能正在寻找“最佳实践”。如果它们在每种情况下都完全相同,那就很好知道。由于它们并不相同,并且确实存在许多“隐藏”的陷阱,这更加重要。请对她宽容点,好吗? - Joe Casadonte
我不能代表Brian说话,但我给她留了足够的余地。有时,“别担心”可能是一个好答案。 - innaM
7个回答

13

perldata perldoc 中得知:

实际上,在大括号内的标识符被强制转换为字符串,作为哈希下标中的任何简单标识符也是如此。它们都不需要引用。我们之前的示例,$days{'Feb'} 可以写成 $days{Feb} ,引号会被自动添加。但是如果在下标中使用了更复杂的内容,则将其解释为表达式。这意味着例如 $version{2.0}++ 相当于 $version{2}++,而不是 $version{'2.0'}++

因此,两者在本质上是相同的。但要注意以下陷阱:

sub is_sub { 'Yep!' }

my %hash;
$hash{ is_sub   } = 'Nope';
$hash{ is_sub() } = 'it is_sub!!';

say Dumper \%hash;

将显示:

$VAR1 = { 'is_sub' => 'Nope', 'Yep!' => 'it is_sub!!' };

我更喜欢使用裸字... 不过如果你要调用子例程,请记得加上那些 () 或者前置的 + (请参见 jrockway 的评论和答案);-)


关于$version{2.0}$version{'2.0'}的例子让我感到困惑,因为这个:perl -e '$foo{'2.0'}=1; print $foo{'2'}++, $foo{2}++, $foo{2.0}++, $foo{1+1}++, "\n";'。花括号中的值被计算为标量,然后该标量被用作键。所以我必须假设您没有测试您的示例,或者我在您试图表达的内容中遗漏了一些微妙之处。(对我来说,它打印1234 - Jim Dennis
很遗憾,您的示例是不正确的。实际上,我甚至感到惊讶它能够正常解析。您在-e和哈希索引中使用了单引号。无论如何,如果您在设置后检查$foo哈希值,您会得到{ '2.0' => 1, '2' => 4 }...这就是您期望看到的答案。 - draegtun
你也可以写成+function而不是function()。 - jrockway
更具体的链接:http://perldoc.perl.org/perldata.html#Scalar-value-constructors - Brad Gilbert

12

它们在功能上是相同的,除非您的键中有空格或其他非字母数字字符。那么您就必须使用带引号的方法。

我更喜欢不使用引号并使用包含alpha_num和下划线的名称。这让我大多数情况下都不用引号。


3
它们在功能上并不相同。在某些情况下,你会得到相同的结果,但是原因并不相同。 - brian d foy
1
жЌ«жбўТў»$hash{"string"}Тў»тљдСИј$hash{string}уЏИтљї№╝їт«ЃС╗гТў»уЏИтљїуџёсђѓ - Artem Russakovskii

8
避免使用引号更符合惯用语。
编辑以添加:
引用并不是绝对易读的解决方案。请考虑这里的不一致性:
sub function() { 'OH HAI' }
my @list = ('foo', 'bar', function); 
# ==> ('foo', 'bar', 'OH HAI')

my %hash;
$hash{'foo'} = 1;
$hash{'bar'} = 2;
$hash{function} = 3;
# ==> { foo => 1, bar => 2, function => 3 } (oops)

当您从不引用字符串时,“奇怪”的东西在视觉上与普通字符串不同...并且它会被正确解析。
$hash{foo} = 1;
$hash{bar} = 2;
$hash{+function} = 3; # aha, this looks different... because it is
# ==> { foo => 1, bar => 2, 'OH HAI' => 3 }

(Stack Overflow的语法高亮会弄乱此处,所以请尽量忽略它。)
(Stack Overflow的语法高亮会干扰这里的内容,请尽量忽略。)

7
大多数人更喜欢不带引号的格式,因为它更加简洁和清晰,只要哈希键被限制为字母数字和下划线。此外,大多数支持Perl语法的编辑器都知道如何突出显示这些字符串,尽管它们不在引号内。
需要注意的是,当您使用哈希键、定义哈希、传递参数或者使用“=>”定义列表时,您可以获得这种行为。在前两种情况下,这有助于在视觉上区分键和值。例如:
# Hash construction
my %hash = ( 
    key1 => "val1",
    key2 => "val2" 
);

# Subroutine arguments
some_function( arg1 => "val1", arg2 => $val2);
sub some_function { my %args = @_; }; # arguments are pulled in as a hash

# List construction (of course, not sure why you'd do this...)
my @list = (Foo => "bar");
print @list; # prints Foobar

话虽如此,我一开始时总是引用所有内容,这已经成为了一种难以改变的习惯。即使过了这么多年,引用哈希键仍然感觉更加“安全”。


更少出错?我看到更多人因为没有使用引号而出错,而不是因为使用了引号。请参考draegtun的答案,其中有一些例子。 - brian d foy
@brian:是的,这两个例子很好,但并不算是很难发现的。句号在字母数字和下划线集合之外,所以很容易被捕捉到。我个人也习惯于始终使用括号来定义用户方法,因此第二种形式对我来说也不会有影响。然而,我向您的丰富经验致敬,并已从我的回复中删除了那句话。 - Adam Bellaire

7

出于追求严谨,我总是在哈希中引用我的字符串引用。这有助于确保我不会遇到意外情况[1]。

[1]在Perl编程中,我比较保守。


1
+1 因为这是一个合理的论点,尽管我倾向于不同意。 - Chris Lutz
1
你是否不同意它可以避免某些陷阱?还是基于风格的原因不同意?我很好奇。 - Paul Nathan
始终使用引号的确可以避免哪些陷阱? - nohat
如果你有一个子 baz() {return 1},那该怎么办?我不知道 foo{baz} 会做什么。我猜测 baz 会被插入到一个字符串中,但是我不确定。我知道 foo{"baz"} 做什么,也知道 foo{baz()} 做什么。 - Paul Nathan
$foo{baz} 总是表示 $foo{baz}。实际上没有任何问题点。如果 $foo{baz} 有时表示其他内容,我会说这是一个问题点,但它并没有,所以不是。 - nohat

4
后一种格式$hash{string}更为简洁,但仅适用于字母数字和下划线。

0

除非你想要$hash{string},否则你应该总是使用$hash{"string"}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接