Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

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;

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top