http://qs1969.pair.com?node_id=411213

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

Why is the following snippet producing a 'syntax error'?

perl -Mstrict -wle"my %x = map{ 'A' => $_ } 1 .. 10" syntax error at -e line 1, near "} 1" Execution of -e aborted due to compilation errors.

Note: I know it may not be logical to assign one key, 10 different values one after the other, but a syntax error?

Note also that both of these are legal:

perl -Mstrict -wle"my %x = map{ $_ => $_ } 1 .. 10" perl -Mstrict -wle"my %x = map{ 'A' . $_ => $_ } 1 .. 10"

But this also isn't "legal syntax" (regardless of whether you use qq// or ""), even though it is logical.

P:\test>perl -Mstrict -wle"my %x = map{ qq[A_$_] => $_ } 1 .. 10" syntax error at -e line 1, near "} 1" Execution of -e aborted due to compilation errors.

So this isn't just a case of over-zealous code policing?

It woudn't be quite so bad if it didn't point you at the wrong part of the statement as the source of the error.

Perl 5.8.4 (AS810).


Examine what is said, not who speaks.
"But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
"Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

Replies are listed 'Best First'.
•Re: Mysterious "syntax error"
by merlyn (Sage) on Nov 30, 2004 at 15:52 UTC
    Because map can take either a block or an expression, and open curly can start a block or an expression (start of an anonymous hash), there's some "guessing" code to deal with the ambiguity, and sometimes it guesses wrong.

    You can disambiguate these with:

    map {; ... definitely a block ... } ... map +{ ... definitely an anonhash ... }, ...
    This is documented in perldata I believe. Or perlref.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      D'uh! I should've worked that out, but ... I didn't.

      I've encountered it before. I may even have asked a SoPW on it a ways back. I'm pretty sure I've answered one or two about it, but I could *not* see the ambiguity. I guess that just shows how infrequently the guessing gets it wrong.

      Thanks.


      Examine what is said, not who speaks.
      "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
      "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
      That doesn't answer the question as to why the two examples BrowserUk listed in his second <code> block work. Those should both be ambiguous, as well, at least to my mind. Would you mind taking a stab at explaining how perl figures those out?

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        If you wanna take a look at the logic of the guess, take a look in toke.c and search for OP_MAPSTART. It's at line 4000 in the 5..8.5 source.

        (I think) The logic for making the guess starts at the comment /* Is this a word before a => operator? */ a few lines below and extends for 100 lines or so. The comments, (if not the code :), make interesting reading as to just how complex this is.


        Examine what is said, not who speaks.
        "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
        "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
        Those should both be ambiguous, as well, at least to my mind
        What part of
        there's some "guessing" code to deal with the ambiguity
        did you miss reading? if you mean "what is the actual rules of the guessing?", well the Perl source code is available for download in about 150 CPAN locations, at least.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

Re: Mysterious "syntax error"
by bart (Canon) on Nov 30, 2004 at 15:52 UTC
    It's the classical block vs. anonymous hash mixup. The syntax is ambiguous, so perl hash to make a guess. Perl wrongly assumes you want an anonymous hash here, thus it's assuming the map EXPR, LIST syntax, so it expects to see a comma. Which isn't there. At that time, perl has gone too far in parsing the source, and it can't backtrack any more, and it throws in the towel.

    Typical solutions are to prepend a "+" if you indeed want an anonymous hash, or put a ";" right after the opening brace, if you want a block. That way, you disambiguate the syntax at an early enough stage.

    • anonymous hash: +{ 'A' => $_ }
    • block: {; 'A' => $_ }
Re: Mysterious "syntax error"
by duff (Parson) on Nov 30, 2004 at 15:54 UTC