Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

strange map behavior

by jeanluca (Deacon)
on Feb 25, 2008 at 17:18 UTC ( [id://670051]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks
Most of the time map surprises me, it always generates output I don't expect. This time however it goes beyond this. Here is my test code:
#! /usr/bin/perl -l use strict; use warnings ; my @arr = qw(1 2 3 4 5) ; my %h = map { "$_" => "$_" } @arr ; print "$_ --> $h{$_}" foreach ( keys %h ) ;
Which returns
syntax error at ./t.pl line 7, near "} @arr " Execution of ./t.pl aborted due to compilation errors.
However when I change the map-line into: my %h = map { $_."" => "$_" } @arr ; it works and produces
4 --> 4 1 --> 1 3 --> 3 2 --> 2 5 --> 5

This is truly map magic for me! Anyone out there who has already walked this path ?

CHeers
LuCa

Update: thnx monks, I appreciate the help!!

Replies are listed 'Best First'.
Re: strange map behavior
by ikegami (Patriarch) on Feb 25, 2008 at 17:27 UTC
    Perl sometimes guesses a block is an anonymous hash constructor and vice-versa.
    my %h = map {; $_ => $_ } @arr; ^ | force a block.
    my @a = map +{ $_ => ord($_) }, @arr; ^ | force a hash

    By the way, why are you using "$_" instead of just $_?

      I tried to build a new hash out of an array with hashes, something like:
      #! /usr/bin/perl -l use strict; use warnings ; my @arr = ( {'a' => 'x', 'b' => 'y', 'c' => 'z'}, {'a' => 'x1', 'b' => 'y1', 'c' => 'z1'} ) ; my %h = map {;"$_->{'a'}_$_->{'c'}" => $_->{'b'} } @arr ; print "$_ -- $h{$_}" foreach ( keys %h ) ;
      Thnx
      LuCa
        That makes more sense. But you might want to use join to increase readability.
        my %h = map { join('_', $_->{'a'}, $_->{'c'}) => $_->{'b'} } @arr ;
Re: strange map behavior
by kyle (Abbot) on Feb 25, 2008 at 17:32 UTC

    This looks like syntax error with map in list context. The documentation for map says "{ starts both hash references and blocks, so map { ... could be either the start of map BLOCK LIST or map EXPR, LIST." This syntax works as well as the one you discovered:

    my %h = map { +"$_" => "$_" } @arr ;
Re: strange map behavior
by CountZero (Bishop) on Feb 25, 2008 at 19:36 UTC
    Why are you trying to confuse Perl by adding useless double quotes? If you drop these double quotes, it works as expected: my %h = map { $_ => $_ } @arr ;

    I have noticed recently that more monks have shown this tendency to add (double) quotes where it is not necessary and I wonder where they may have picked-up such a strange idea? Is there a new "Perl for Beginners Tutorial" running loose somewhere? If so, we need to catch it and have it shot.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      I wonder where they may have picked-up such a strange idea?

      In this case, the quotes are a remnant of his fuller code (it's almost a case of "show us the real code, not an unrepresentative sample"), see Re^2: strange map behavior. But in many cases, the tendency to over-quote can be attributed to converted shell scripters. In Bourne shells (and probably many others), you need to quote your variables to have them remain discrete values -- otherwise spaces and other whitespace can break them up into multiple tokens.

Re: strange map behavior
by Anonymous Monk on Feb 25, 2008 at 19:12 UTC
    Your using a 'fat comma' (aka the "quoting comma": =>).
    The argument to the left does not need to be quoted, try this...

    my %h = map { $_ => "$_" } @arr ;
      Your using a 'fat comma' (aka the "quoting comma": =>)

      That is a very confusing statement.

      From the mouth of the Camel:

      The => operator is just a synonym for a comma, but it's more visually distinctive and also quotes any bare identifiers to the left of it.

      $_ not being a bare identifier, the 'fat comma' is just a comma here.

      Actually my %h = map { "$_" , "$_" } @arr ; gives the same syntax error as my %h = map { "$_" => "$_" } @arr ; proving that the 'fat comma' has nothing to do with the error. It are the double quotes that confuse the interpreter.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        Hey, thanks. I should have checked that the ordinary ',' operator worked similarly in this situation before I posted. I stand corrected and educated.
Re: strange map behavior
by alexm (Chaplain) on Feb 26, 2008 at 20:28 UTC
    This should work too and it's much easier to remember for me:
    my %h = map { ("$_" => "$_") } @arr ;

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2024-03-19 08:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found