4

为什么以下有效?

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

并且以下无效?

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

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

4

3 回答 3

8

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

就像grep它支持两种不同的语法

map BLOCK LIST
map EXPR, LIST

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

my @ys = map { $_ * $_ } @xs;
my @ys = map $_ * $_, @xs;
于 2013-09-26T16:17:35.763 回答
4

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

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

于 2013-09-26T16:49:18.813 回答
1

它是一个运算符,每个运算符都定义了自己的语法。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
  • ETC

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

于 2013-09-26T17:13:29.020 回答