http://qs321.pair.com?node_id=510234

LucaPette has asked for the wisdom of the Perl Monks concerning the following question:

I have written the following code:
#!/usr/bin/perl -w use strict; my %data=map { "Player number $_", [ map { 1 + int rand(10) } 1 .. 5 ] } 1 .. 10; print "$_ @{$data{$_}}\n" for ( keys %data );
It doesn't work, infact perl prints an error like this:
syntax error at ./mytest line 9, near "} 1" Execution of ./mytest aborted due to compilation errors.
To resolve the problem i have changed this chuck of code:
my %data=map { "Player number $_", [ map { 1 + int rand(10) } 1 .. 5 ] } 1 .. 10;
with this:
my %data=map { "Player number " . $_, [ map { 1 + int rand(10) } 1 .. 5 ] } 1 .. 10;

With the latter chuck of code the little program works and prints an output like this:

Player number6 6 7 3 2 7 Player number2 3 2 6 7 8 Player number7 1 7 3 7 1 Player number1 8 10 4 7 4 Player number10 1 2 5 1 3 Player number9 1 4 10 4 8 Player number4 4 1 4 5 5 Player number3 8 6 9 5 6 Player number5 9 3 5 6 6 Player number8 10 3 8 8 1
Now i am wondering which is the problem with the former code but i am not be
able to find an answer.
Can someone help me to find the right answer?

Replies are listed 'Best First'.
Re: syntax error with map in list context
by dave0 (Friar) on Nov 20, 2005 at 13:38 UTC
    It's a known issue with Perl guessing wrong on the meaning of the initial {. See the Perldoc for map, in the paragraph beginning:

    "{" starts both hash references and blocks, so "map { ..." could be either the start of map BLOCK LIST or map EXPR, LIST.

    There are examples of how to avoid the problem in that doc, but my suggestion would be:

    my %data = map +( "Player number $_" => [ map { 1 + int rand(10) } 1 .. 5 ] ), 1 .. 10;
Re: syntax error with map in list context
by Aristotle (Chancellor) on Nov 20, 2005 at 17:52 UTC

    There are two ways to unconfuse perl about whether you mean a block or an anonymous hash, depending on which one it is:

    1. +{ ... } is always considered an anonymous hash. The unary plus is generally used to explicitly signify that what follows is an expression.

    2. {; ... } is always considered a block.

    You’ll find that if you write your code as map {; ... } ..., it works.

    Makeshifts last the longest.

Re: syntax error with map in list context
by pg (Canon) on Nov 20, 2005 at 17:26 UTC

    Another way to force Perl to take your code is to add a pair of (), which seems clean and simple to me:

    use strict; my %data=map { ("Player number $_"), [ map { 1 + int rand(10) } 1 .. 5 ] } 1 .. 10; print "$_ @{$data{$_}}\n" for ( keys %data );
Re: syntax error with map in list context
by davidrw (Prior) on Nov 20, 2005 at 12:48 UTC
    Hmm.. interesting.. Played with a bit, and found that this works:
    my %data=map { +"Player number $_", [ map { 1 + int rand(10) } 1 .. 5 ] } 1 .. 10;
    I'm can't explain why, but hopefully someone will help clarify.. must be related to evaluation order or something like that.

    Two side comments .. This does (nearly) the same thing:
    my %data=map { $_ => [ map { 1 + int rand(10) } 1 .. 5 ] } 1 .. 10;
    First change is using => instead of a comma -- this makes it more obvious to the reader that you're constructing key-value pairs. Second is just making the key be the player number -- this might be useful to you later in the code, and then you can include the text "Player number" only when you're actually print'ing out the data later.