问题
Why is the following valid?
my @ys = map { $_ * $_ } @xs;
And the following invalid?
my @ys = map { $_ * $_ }, @xs;
Is map
a language construct and not really a function, or are there special rules for blocks?
回答1:
map
is list operator and a core function. It is simple Perl syntax that expects no comma after a block parameter to a subroutine. The special thing about map
is that it can also take the form map EXPR, LIST
. If this was used with a standard subroutine the EXPR
would just be evaluated and passed as the first parameter.
Block parameters are valid for all subroutines, and can be used if you apply prototypes to your subroutine definition. For instance, you could define a mymap
that behaved just the same way by writing
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;
output
1
4
9
But in general you should avoid prototypes unless you know exactly what you are doing. There is generally a better way to write your code.
回答2:
Yes, map
is a language construct.
Like grep, it supports two different syntaxes:
map BLOCK LIST
map EXPR, LIST
The BLOCK
in your example is just a simple expression, so these two statements are equivalent:
my @ys = map { $_ * $_ } @xs;
my @ys = map $_ * $_, @xs;
回答3:
It's an operator, and each operator defines its own syntax. Perl provides the tools for subroutines can do that too.
The opening line of perlfunc is:
The functions in this section can serve as terms in an expression. They fall into two major categories: list operators and named unary operators.
So while map
isn't a function in the C sense —those are called subroutines in Perl— it is a function by Perl's definition.
So map
is an operator. Lots of operators have subroutines that differ from subroutine calls:
substr
(Must be followed by 1 to 4 comma-separated expressions)time
(Can't be given an argument list)map BLOCK LIST
print BLOCK LIST
delete HASH_ELEMENT
push ARRAY, LIST
lc
(Where the calling scope's$_
is provided)EXPR + EXPR
- etc
Subroutines can match or approximate the syntax of named operators using prototypes (e.g. sub mypush(\@@)
) and Devel::CallParser (e.g. loop).
来源:https://stackoverflow.com/questions/19033299/why-is-no-comma-needed-between-the-arguments-to-map