9

This throws an error in Perl v5.20:

use strict;
use warnings;
my @a = (2,3,9);
my %b = map { "number $_" => 2*$_ } @a;

Error:

syntax error at a.pl line 4, near "} @a"
Execution of a.pl aborted due to compilation errors.

This doesn't:

use strict;
use warnings;
my @a = (2,3,9);
my %b = map { "number ".$_ => 2*$_ } @a;

Why is interpolation of $_ disallowed within the map BLOCK?

ikegami
  • 367,544
  • 15
  • 269
  • 518

1 Answers1

14

map has two syntax:

map BLOCK LIST
map EXPR, LIST

Perl must determine which syntax you are using. The problem is that both BLOCK and EXPR can start with { because { ... } can be the hash constructor (e.g. my $h = { a => 1, b => 2 };).

That means that Perl's grammar is ambiguous. When an ambiguity is encountered, perl guesses what you mean after looking ahead a little. In your situation, it guessed wrong. It guessed { was the start of a hash constructor instead of the start of a block. You will need to disambiguate explicitly.

The following are convenient ways to disambiguate blocks and hash constructors:

+{ ... }   # Not a valid block, so must be a hash constructor.
{; ... }   # Perl looks head, and sees that this must be a block.

So in your case, you could use

my %b = map {; "number $_" => 2*$_ } @a;

Related: Difference between returning +{} or {} in perl from a function, and return ref or value

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    @Сухой27, The error message is more precise with `+{ ... }`, but it's the same error: a comma is expected after the end of the expression. – ikegami Nov 15 '17 at 15:52