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

$_ and list flattening with map()

by liz (Monsignor)
on Dec 14, 2003 at 21:05 UTC ( #314681=perlquestion: print w/ replies, xml ) Need Help??
liz has asked for the wisdom of the Perl Monks concerning the following question:

Aristotle's answer to Switching on internal UTF-8 flaq on DBI result from database made me find the following phenomenon:
$a = [[0]]; foreach (@$a) { $_++ foreach @$_ } print $a->[0][0],$/; $_++ for map @$_, @{$a}; print $a->[0][0],$/; __END__ 1 1
The expected output is:
1 2
The strange thing is that the extra list flattening with map() doesn't work. I don't see any reason why it shouldn't. I guess the question is: is this a bug or not?

Liz

Update:
Not a bug, just copying of the list with map(). Thanks to !1, blokhead and holo for the enlightenment.

Comment on $_ and list flattening with map()
Select or Download Code
Re: $_ and list flattening with map()
by !1 (Hermit) on Dec 14, 2003 at 21:18 UTC

    I always thought map just returns copies of the values?

    my @a = qw(1 2); my @b = \(@a); my @c = \(map $_,@a); print "Addresses do not match$/" unless "@b" eq "@c"; __END__ Addresses do not match

    Of course, changing your map to:

    ${$_}++ for map \(@$_),@{$a};

    Will make it work as expected.

Re: $_ and list flattening with map()
by blokhead (Monsignor) on Dec 14, 2003 at 21:23 UTC
    $_++ for map @$_, @{$a};
    The difference is that you do the increment outside of the scope in which map aliases $_. This foreach is iterating over the return value of map, which is a list of copies (not aliases back into @$a). foreach now aliases $_ to this anonymous list of copies, so your modifications to $_ are lost.

    If you use map as a control structure (making it more of a direct translation of the first example), and do the increment inside map's block, you'll get what you expected originally:

    map { map { $_++ } @$_ } @$a;

    blokhead

Re: $_ and list flattening with map()
by holo (Monk) on Dec 14, 2003 at 21:44 UTC

    The line:

    $_++ for map $_, @a;

    generates an anonymous list with map, then iterates through it with for incrementing all its values. Once for is done, the list is thrown away (expensive no-op).

    The line:

    $_++ for my @b = map $_, @a;

    generates a list with map and throws it in @b, then iterates through it with for incrementing all values as before. This time, the list is not anonymous and may be accessed by using @b and it's not thrown away. Once map is evaluated, values in @b are totaly independent from values in @a.

Re: $_ and list flattening with map()
by pg (Canon) on Dec 14, 2003 at 22:05 UTC

    This tells why:

    use strict; use warnings; use Data::Dumper; my $a = [[0,1,2], [10,11,12]]; print \$a->[0][0], "\n"; print \$a->[0][1], "\n"; print \$a->[0][2], "\n"; print \$a->[1][0], "\n"; print \$a->[1][1], "\n"; print \$a->[1][2], "\n"; print "=======\n"; print \$_, "\n" for map @$_, @{$a};#one of your way print "=======\n"; foreach (@$a) { print \$_, "\n" foreach @$_ }#your other way

    Result, see how the 3rd set is the same as the 1st one, but the 2nd set stands alone:

    SCALAR(0x15551a4) SCALAR(0x15551b0) SCALAR(0x15551c8) SCALAR(0x155abd4) SCALAR(0x155500c) SCALAR(0x1571284) ======= SCALAR(0x15712c0) SCALAR(0x1571290) SCALAR(0x15551d4) SCALAR(0x15712e4) SCALAR(0x15712d8) SCALAR(0x15712cc) ======= SCALAR(0x15551a4) SCALAR(0x15551b0) SCALAR(0x15551c8) SCALAR(0x155abd4) SCALAR(0x155500c) SCALAR(0x1571284)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (7)
As of 2015-07-03 11:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (51 votes), past polls