我在使用c()
函数的Perl程序中遇到了奇怪的语法错误。我有一个简单的解决方法(添加看似不必要的括号),所以这不是关键,但我不知道为什么Perl报告原始代码的语法错误,或者为什么添加括号修复它。
我想创建一个哈希,将一系列短字符串映射到值map
(基本上是一组数据结构),每个字符串以' - '开头。我的第一次尝试与此类似:
1
我认为应该相当于:
my %hash = map { "-$_" => 1 } qw(foo bar);
Perl报告了语法错误。如果我用任何单引号或双引号字符串文字替换my %hash = ( "-foo" => 1, "-bar" => 1 );
,我会收到语法错误。如果我将"-$_"
替换为"-$_"
,语法错误就会消失,代码也能正常运行。
我在Perl 5.10.1,5.16.2和5.20.0中获得了类似的结果。
这是一个显示问题的自包含脚本(我删除了("-$_")
前缀,因为它似乎并不相关):
-
以及我尝试使用Perl 5.20.0运行它时的输出:
#!/usr/bin/perl
use strict;
use warnings;
my %h0 = map { $_ => 1 } qw(foo bar); # ok
my %h1 = map { ("$_") => 1 } qw(foo bar); # ok
my %h2 = map { "$_" => 1 } qw(foo bar); # line 8, syntax error
my %h3 = map { 'FOO' => 1 } qw(foo bar); # line 9, syntax error
my %h4 = map { "FOO" => 1 } qw(foo bar); # line 10, syntax error
(使用Perl 5.10.1和5.16.2,它也会抱怨"地图上没有足够的参数"第8行。)
我已经确认,当其他两行被注释掉时,三个语法错误中的每一个仍然是孤立的,因此第9行和第10行不是来自第8行的级联错误。
这是Perl中的一个错误,还是我错过了Perl语法的一些细微之处,或其他什么?
答案 0 :(得分:4)
{
启动散列引用和块,因此map { ...
可以是映射BLOCK LIST的开头或映射EXPR,LIST。因为Perl没有提前结束}
,所以它必须根据{
之后的内容来猜测它正在处理什么。通常它是正确的,但如果它没有意识到某些事情是错误的,直到它到达}
并遇到丢失(或意外)的逗号。语法错误将在}
附近报告,但您需要更改{
附近的内容,例如使用一元+
或分号为Perl提供一些帮助:%hash = map { "\L$_" => 1 } @array # perl guesses EXPR. wrong %hash = map { +"\L$_" => 1 } @array # perl guesses BLOCK. right %hash = map {; "\L$_" => 1 } @array # this also works %hash = map { ("\L$_" => 1) } @array # as does this %hash = map { lc($_) => 1 } @array # and this. %hash = map +( lc($_) => 1 ), @array # this is EXPR and works! %hash = map ( lc($_), 1 ), @array # evaluates to (1, @array)
或强制anon哈希构造函数使用
+{
:@hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs # comma at end
获取一个匿名哈希列表,每个哈希只有一个条目。