为什么以下有效?
my @ys = map { $_ * $_ } @xs;
并且以下无效?
my @ys = map { $_ * $_ }, @xs;
是map
语言构造而不是真正的函数,还是对块有特殊规则?
为什么以下有效?
my @ys = map { $_ * $_ } @xs;
并且以下无效?
my @ys = map { $_ * $_ }, @xs;
是map
语言构造而不是真正的函数,还是对块有特殊规则?
是的,map
是一种语言结构。
就像grep
,它支持两种不同的语法:
map BLOCK LIST
map EXPR, LIST
您的示例中的 theBLOCK
只是一个简单的表达式,因此这两个语句是等价的:
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 LIST
print BLOCK LIST
delete HASH_ELEMENT
push ARRAY, LIST
lc
(提供调用范围的地方$_
)EXPR + EXPR
sub mypush(\@@)
子例程可以使用原型(例如)和Devel::CallParser(例如)匹配或近似命名运算符的语法loop
。