【问题标题】:Why is no comma needed between the arguments to map?为什么映射的参数之间不需要逗号?
【发布时间】:2013-09-26 16:09:51
【问题描述】:

为什么以下有效?

my @ys = map { $_ * $_ } @xs;

而以下无效?

my @ys = map { $_ * $_ }, @xs;

map 是一种语言结构,而不是真正的函数,还是对块有特殊的规则?

【问题讨论】:

  • 这些情况下的“为什么”是“因为拉里决定这样做”。 :)

标签: perl higher-order-functions


【解决方案1】:

是的,map 是一种语言结构。

点赞grepit supports two different syntaxes

map BLOCK LIST
map EXPR, LIST

您示例中的BLOCK 只是一个简单的表达式,因此这两个语句是等价的:

my @ys = map { $_ * $_ } @xs;
my @ys = map $_ * $_, @xs;

【讨论】:

    【解决方案2】:

    map列表运算符核心函数。这是一种简单的 Perl 语法,在子例程的块参数之后不需要逗号。 map 的特别之处在于它也可以采用map EXPR, LIST 的形式。如果这与标准子例程一起使用,EXPR 将被评估并作为第一个参数传递。

    块参数对所有子程序都有效,并且可以在您将原型应用于子程序定义时使用。例如,您可以定义一个 mymap,其行为方式与编写方式相同

    use strict;
    use warnings;
    use 5.010;
    
    sub mymap(&@) {
      use Data::Dump;
      my $sub = shift;
      my @newlist;
      push @newlist, $sub->($_) for @_;
      @newlist;
    }
    
    say for mymap { $_ * $_ } 1, 2, 3;
    

    输出

    1
    4
    9
    

    但一般而言,除非您确切地知道自己在做什么,否则您应该避免原型。通常有更好的方法来编写您的代码。

    【讨论】:

      【解决方案3】:

      它是一个运算符,每个运算符都定义了自己的语法。 Perl 提供了子程序的工具也可以做到这一点。


      perlfunc的开头行是:

      本节中的函数可以用作表达式中的术语。它们分为两大类:列表运算符和命名一元运算符。

      因此,虽然map 不是 C 意义上的函数(在 Perl 中称为子例程),但它是 Perl 定义的函数。

      所以map 是一个运算符。许多运算符都有与子程序调用不同的子程序:

      • substr(后面必须跟 1 到 4 个逗号分隔的表达式)
      • time(无法给出参数列表)
      • map BLOCK LIST
      • print BLOCK LIST
      • delete HASH_ELEMENT
      • push ARRAY, LIST
      • lc(提供了调用范围的$_
      • EXPR + EXPR

      子例程可以使用原型(例如sub mypush(\@@))和Devel::CallParser(例如loop)匹配或近似命名运算符的语法。

      【讨论】:

        猜你喜欢
        • 2017-05-18
        • 2011-05-10
        • 1970-01-01
        • 1970-01-01
        • 2015-09-23
        • 1970-01-01
        • 2022-07-16
        • 2020-05-20
        • 1970-01-01
        相关资源
        最近更新 更多