Why does Perl function "map" give the error "Not enough arguments for map"

dictionary, perl

Solution

Perl uses heuristics to decide whether you're using:

map { STATEMENTS } LIST;   # or
map EXPR, LIST;

Because although "{" is often the start of a block, it might also be the start of a hashref.

These heuristics don't look ahead very far in the token stream (IIRC two tokens).

You can force "{" to be interpreted as a block using:

map {; STATEMENTS } LIST;    # the semicolon acts as a disambigator

You can force "{" to be interpreted as a hash using:

map +{ LIST }, LIST;    # the plus sign acts as a disambigator

`grep` suffers similarly. (Technically so does `do`, in that a hashref can be given as an argument, which will then be stringified and treated as if it were a filename. That's just weird though.)

Problem

Here is the thing I don't understand. This script works correctly (notice the concatenation in the map functin): ``` #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %aa = map { 'a' . '' => 1 } (1..3); print Dumper \%aa; __END__ output: $VAR1 = { 'a' => 1 }; ``` But without concatenation the map does not work. Here is the script I expect to work, but it does not: ``` #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %aa = map { 'a' => 1 } (1..3); print Dumper \%aa; __END__ output: Not enough arguments for map at e.pl line 7, near "} (" syntax error at e.pl line 7, near "} (" Global symbol "%aa" requires explicit package name at e.pl line 9. Execution of e.pl aborted due to compilation errors. ``` Can you please explain such behaviour?

Original source