2

我在使用该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 行抱怨“没有足够的参数用于 map”。)

我已经确认,当其他两行被注释掉时,三个语法错误中的每一个仍然单独发生,因此第 9 行和第 10 行不是第 8 行的级联错误。

这是 Perl 中的一个错误,还是我错过了 Perl 语法的一些微妙之处,或者其他什么?

4

1 回答 1

4

perldoc -f map

{开始哈希引用和块,因此map { ...可以是映射块列表或映射 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)

或强制使用匿名哈希构造函数+{

    @hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs
                                           # comma at end

获取一个匿名哈希列表,每个哈希只有一个条目。

于 2015-07-29T23:17:04.927 回答