【发布时间】:2013-09-26 16:09:51
【问题描述】:
为什么以下有效?
my @ys = map { $_ * $_ } @xs;
而以下无效?
my @ys = map { $_ * $_ }, @xs;
map 是一种语言结构,而不是真正的函数,还是对块有特殊的规则?
【问题讨论】:
-
这些情况下的“为什么”是“因为拉里决定这样做”。 :)
标签: perl higher-order-functions
为什么以下有效?
my @ys = map { $_ * $_ } @xs;
而以下无效?
my @ys = map { $_ * $_ }, @xs;
map 是一种语言结构,而不是真正的函数,还是对块有特殊的规则?
【问题讨论】:
标签: perl higher-order-functions
是的,map 是一种语言结构。
点赞grep、it supports two different syntaxes:
map BLOCK LIST
map EXPR, LIST
您示例中的BLOCK 只是一个简单的表达式,因此这两个语句是等价的:
my @ys = map { $_ * $_ } @xs;
my @ys = map $_ * $_, @xs;
【讨论】:
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
但一般而言,除非您确切地知道自己在做什么,否则您应该避免原型。通常有更好的方法来编写您的代码。
【讨论】:
它是一个运算符,每个运算符都定义了自己的语法。 Perl 提供了子程序的工具也可以做到这一点。
perlfunc的开头行是:
本节中的函数可以用作表达式中的术语。它们分为两大类:列表运算符和命名一元运算符。
因此,虽然map 不是 C 意义上的函数(在 Perl 中称为子例程),但它是 Perl 定义的函数。
所以map 是一个运算符。许多运算符都有与子程序调用不同的子程序:
substr(后面必须跟 1 到 4 个逗号分隔的表达式)time(无法给出参数列表)map BLOCK LISTprint BLOCK LISTdelete HASH_ELEMENTpush ARRAY, LISTlc(提供了调用范围的$_)EXPR + EXPR子例程可以使用原型(例如sub mypush(\@@))和Devel::CallParser(例如loop)匹配或近似命名运算符的语法。
【讨论】: