Why is no comma needed between the arguments to map?

穿精又带淫゛_ 提交于 2019-12-23 12:09:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!