使用 map 函数的语法错误
Syntax error using map function
我在使用 map
函数的 Perl 程序中遇到了一个奇怪的语法错误。我有一个简单的解决方法(添加看似不必要的括号),所以这不是关键,但我不知道为什么 Perl 在原始代码上报告语法错误,或者为什么添加括号修复它。
我想创建一个散列,将一系列短字符串映射到值 1
(基本上是一组数据结构),每个字符串都以“-”开头。我的第一次尝试与此类似:
my %hash = map { "-$_" => 1 } qw(foo bar);
我认为应该等同于:
my %hash = ( "-foo" => 1, "-bar" => 1 );
Perl 报告语法错误。如果我将 "-$_"
替换为任何单引号或双引号字符串文字,我会收到语法错误。如果我将 "-$_"
替换为 ("-$_")
,语法错误就会消失,并且代码可以正常工作。
我在 Perl 5.10.1、5.16.2 和 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.20.0 运行 时的输出:
syntax error at map-bug line 8, near "} qw(foo bar)"
syntax error at map-bug line 9, near "} qw(foo bar)"
syntax error at map-bug line 10, near "} qw(foo bar)"
Execution of map-bug aborted due to compilation errors.
(对于 Perl 5.10.1 和 5.16.2,它还会在第 8 行抱怨 "Not enough arguments for map"。)
我已经确认,当其他两行被注释掉时,三个语法错误中的每一个仍然单独出现,因此第 9 行和第 10 行不是第 8 行的级联错误。
这是 Perl 中的错误,还是我遗漏了 Perl 语法的一些微妙之处,或者其他什么?
{
starts both hash references and blocks, so map { ...
could be either the start of map BLOCK LIST or map EXPR, LIST. Because Perl doesn't look ahead for the closing }
it has to take a guess at which it's dealing with based on what it finds just after the {
. Usually it gets it right, but if it doesn't it won't realize something is wrong until it gets to the }
and encounters the missing (or unexpected) comma. The syntax error will be reported close to the }
, but you'll need to change something near the {
such as using a unary +
or semicolon to give Perl some help:
%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)
or to force an anon hash constructor use +{
:
@hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs
# comma at end
to get a list of anonymous hashes each with only one entry apiece.
我在使用 map
函数的 Perl 程序中遇到了一个奇怪的语法错误。我有一个简单的解决方法(添加看似不必要的括号),所以这不是关键,但我不知道为什么 Perl 在原始代码上报告语法错误,或者为什么添加括号修复它。
我想创建一个散列,将一系列短字符串映射到值 1
(基本上是一组数据结构),每个字符串都以“-”开头。我的第一次尝试与此类似:
my %hash = map { "-$_" => 1 } qw(foo bar);
我认为应该等同于:
my %hash = ( "-foo" => 1, "-bar" => 1 );
Perl 报告语法错误。如果我将 "-$_"
替换为任何单引号或双引号字符串文字,我会收到语法错误。如果我将 "-$_"
替换为 ("-$_")
,语法错误就会消失,并且代码可以正常工作。
我在 Perl 5.10.1、5.16.2 和 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.20.0 运行 时的输出:
syntax error at map-bug line 8, near "} qw(foo bar)"
syntax error at map-bug line 9, near "} qw(foo bar)"
syntax error at map-bug line 10, near "} qw(foo bar)"
Execution of map-bug aborted due to compilation errors.
(对于 Perl 5.10.1 和 5.16.2,它还会在第 8 行抱怨 "Not enough arguments for map"。)
我已经确认,当其他两行被注释掉时,三个语法错误中的每一个仍然单独出现,因此第 9 行和第 10 行不是第 8 行的级联错误。
这是 Perl 中的错误,还是我遗漏了 Perl 语法的一些微妙之处,或者其他什么?
{
starts both hash references and blocks, somap { ...
could be either the start of map BLOCK LIST or map EXPR, LIST. Because Perl doesn't look ahead for the closing}
it has to take a guess at which it's dealing with based on what it finds just after the{
. Usually it gets it right, but if it doesn't it won't realize something is wrong until it gets to the}
and encounters the missing (or unexpected) comma. The syntax error will be reported close to the}
, but you'll need to change something near the{
such as using a unary+
or semicolon to give Perl some help:%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)
or to force an anon hash constructor use
+{
:@hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs # comma at end
to get a list of anonymous hashes each with only one entry apiece.