【问题标题】:Why does Perl function "map" give the error "Not enough arguments for map"为什么 Perl 函数“map”会给出错误“Not enough arguments for map”
【发布时间】:2014-01-09 22:39:42
【问题描述】:

这是我不明白的地方。

这个脚本可以正常工作(注意 map functin 中的连接):

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %aa = map { 'a' . '' => 1 } (1..3);

print Dumper \%aa;

__END__
output:

$VAR1 = {
          'a' => 1
        };

但是如果没有连接,地图就无法工作。这是我希望工作的脚本,但它没有:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my %aa = map { 'a' => 1 } (1..3);

print Dumper \%aa;
__END__
output:

Not enough arguments for map at e.pl line 7, near "} ("
syntax error at e.pl line 7, near "} ("
Global symbol "%aa" requires explicit package name at e.pl line 9.
Execution of e.pl aborted due to compilation errors.

你能解释一下这种行为吗?

【问题讨论】:

    标签: perl dictionary


    【解决方案1】:

    Perl 使用启发式方法来决定您是否正在使用:

    map { STATEMENTS } LIST;   # or
    map EXPR, LIST;
    

    因为虽然“{”通常是块的开头,但它也可能是 hashref 的开头。

    这些启发式算法在令牌流(IIRC 两个令牌)中的预测并不远。

    您可以使用以下命令强制将“{”解释为块:

    map {; STATEMENTS } LIST;    # the semicolon acts as a disambigator
    

    您可以使用以下命令强制将“{”解释为哈希:

    map +{ LIST }, LIST;    # the plus sign acts as a disambigator
    

    grep 遭受同样的痛苦。 (从技术上讲,do 也是如此,因为可以将 hashref 作为参数给出,然后将其字符串化并将其视为文件名。不过这很奇怪。)

    【讨论】:

      【解决方案2】:

      根据Documentationmap

      因为 Perl 不会提前结束 },它必须根据在 { 之后发现的内容来猜测它正在处理的内容。通常它是正确的,但如果不是,它不会意识到有什么问题,直到它到达}

      举例说明:

      %hash = map {  "\L$_" => 1  } @array # perl guesses EXPR. wrong
      %hash = map { +"\L$_" => 1  } @array # perl guesses BLOCK. right
      

      所以添加+ 将得到与您给出的第一个示例相同的结果

      my %aa = map {  +'a'=> 1 } (1..3);
      

      【讨论】:

      • 与您的答案无关,但是将编程语言的语法建立在猜测的基础上并不完全让我觉得是好的设计。
      【解决方案3】:

      Perl 的 manpage entry for map() 解释了这一点:

      "{" 开始哈希引用和块,所以 "map { ..." 可以是映射 BLOCK LIST 或映射 EXPR、LIST 的开始。 因为 Perl 不会提前寻找结束的“}”,所以它必须 根据发现的内容猜测它正在处理的内容 就在“{”之后。通常它是正确的,但如果它不正确 在到达“}”之前它不会意识到有什么问题 并遇到缺少的(或意外的)逗号。语法 错误将在“}”附近报告,但您需要 更改“{”附近的内容,例如使用一元“+”给 Perl 一些帮助: %hash = map { "\L$_" => 1 } @array # perl 猜测 EXPR。错误的 %hash = map { +"\L$_" => 1 } @array # perl 猜测 BLOCK。对 %hash = map { ("\L$_" => 1) } @array # 这也有效 %hash = map { lc($_) => 1 } @array # 就像这样。 %hash = map +( lc($_) => 1 ), @array # 这是 EXPR 并且有效! %hash = map ( lc($_), 1 ), @array # 计算结果为 (1, @array) 或强制匿名哈希构造函数使用“+{”: @hashes = map +{ lc($_) => 1 }, @array # EXPR,所以最后需要逗号 获取一个匿名哈希列表,每个哈希只有一个条目 一块。

      基于此,要消除串联杂乱,您需要将语法调整为以下之一:

      my %aa = map { +'a' => 1 } (1..3);
      my %aa = map { ('a' => 1) } (1..3);
      my %aa = map +( 'a' => 1 ), (1..3);
      

      【讨论】:

        【解决方案4】:

        大括号在地图的上下文中有点模棱两可。它们可以按照您的意图围绕一个块,或者它们可以是一个匿名哈希构造函数。 perl 解析器中有一些模糊逻辑试图猜测您的意思。

        您的第二种情况看起来更像是 perl 的匿名哈希。

        请参阅perldoc for map,其中解释了这一点并提供了一些解决方法。

        【讨论】:

          猜你喜欢
          • 2023-02-04
          • 1970-01-01
          • 1970-01-01
          • 2020-09-20
          • 1970-01-01
          • 2021-08-04
          • 1970-01-01
          • 2022-01-08
          • 1970-01-01
          相关资源
          最近更新 更多