Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

map syntax bug-a-boo?

by MeowChow (Vicar)
on Nov 30, 2001 at 08:32 UTC ( [id://128551]=perlquestion: print w/replies, xml ) Need Help??

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

Well, it's been a few months, and I fear my Perl skills are getting rusty, but I'm almost certain the following lines should not be generating syntax errors:
  
@l = 1..10; map { 1, 2 } @l; map { "$_", 2 } @l;
eh?
   MeowChow                                   
               s aamecha.s a..a\u$&owag.print

Replies are listed 'Best First'.
Re: map syntax bug-a-boo?
by chipmunk (Parson) on Nov 30, 2001 at 09:53 UTC
    Curly braces can denote a block or an anonymous hash, and map can take a block or an expression, so map followed by a curly brace is ambiguous. Unfortunately, perl doesn't look forward to the closing brace to see whether it's a block or an anonymous hash, so perl has to guess.

    If the opening curly brace is followed by a string and a comma (, or =>), perl guesses it's an anonymous hash. Anything else, and perl guesses it's a block. This heuristic works most of the time, but in some cases perl guesses wrong:

    # a block returning a list of two elements, # but perl thinks it's an anonymous hash %hash = map { "$_", 2 } @l; # an anonymous hash, but perl thinks it's a block @hash_refs = map { $_, 2 }, @l;
    However, there's not much urgency to fix this problem, because it's so easy to avoid:
    # force parsing as a block %hash = map { +"$_", 2 } @l; %hash = map { ; "$_", 2 } @l; %hash = map { ( "$_", 2) } @l; # force parsing as an anonymous hash @hash_refs = map +{ $_, 2 }, @l;
      Can I ask a silly question? What does the + mean to Perl in these examples. I don't ever recall seeing it ever used in such a way.

      -Lee

      "To be civilized is to deny one's nature."

        It's like making explicit the implicit '+' that precedes any non-negative number (think scalar ::= number or string).

        Do you remember, when learning how to format numbers for output (using '%f', '%g', etc.) with printf in C, you had to account for the sign position? It would display as either a hyphen or blank. A blank, however, was analagous to a plus-sign.

        Likewise, on input, non-negative numbers could optionally be expressed with a leading plus-sign. Since scalars (or scalar expressions) may be either numbers or a strings in perl, perl allows this with arbitrary scalar expressions.

        dmm

        
        You can give a man a fish and feed him for a day ...
        Or, you can teach him to fish and feed him for a lifetime
        
        Unary minus negates its operand, either adding a minus sign, or switching a minus sign to a plus sign or vice versa. Unary plus, on the other hand, returns its operand completely unchanged. Why is this useful? It can come in handy when dealing with ambiguous syntax.

        More examples of unary plus:

        print (3-1)*2; # oops! print (...) interpreted as function ... print +(3-1)*2; sub foo { $foo } $h{foo}; # equivalent to $h{'foo'} $h{+foo}; # but maybe you meant $h{foo()}
        See perlop for more on this curious operator.
Re: map syntax bug-a-boo?
by dvergin (Monsignor) on Nov 30, 2001 at 08:41 UTC
    Now, brethren and sistern, let's all charitabley agree to stipulate that the horrid "map in a void context" was merely for the purpose of reducing the problem to its bare essentials.

    It would appear that, because of what you have put inside the {...}, Perl is taking that to be an expression and thus needing a comma after it.

    use strict; my @l = 1..10; map { 1, 2 }, @l; map { "$_", 2 }, @l;
    does not produce errors. And if you say:
    print map { 1, 2 }, @l; print map { "$_", 2 }, @l;
    you will see a bunch of hash-refs. So Perl is seeing {1,2} as an anonymous hash rather than as a BLOCK that happens to return something. (A very reasonable reading now that we look at it that way.)

    ------------------------------------------------------------
    "Perl is a mess and that's good because the
    problem space is also a mess.
    " - Larry Wall

      I was thinking along the same lines, but the fact that the following does work seems to contradict this argument, or at least imply that it's not the whole story:
      map { $_, 2 } @l;
      Though, now that I think about it, all this probably reflects a perl heuristic/optimization in the parser which says something along the lines of "if, within the bracketed expression, I see a constant and then a comma, I'm going to assume the expression is a hash, and not a block, no matter what comes afterwards...."
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
Re (tilly) 1: map syntax bug-a-boo?
by tilly (Archbishop) on Nov 30, 2001 at 08:51 UTC
    The easy way to get it to parse the way you want is:
    map {($_, 2)} @l;
(crazyinsomniac) Re: map syntax bug-a-boo?
by crazyinsomniac (Prior) on Nov 30, 2001 at 08:52 UTC
    Try print {}; then print {1 => 2}; and then print {1 , 2}; and finally print map { ( 1,2 ) } @l;

    update: Howdy folks, I'm a slowhand luke

     
    ___crazyinsomniac_______________________________________
    Disclaimer: Don't blame. It came from inside the void

    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://128551]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2024-04-23 23:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found