in reply to Code clarification - use of map and $$_

while (<IN>) { our(@F) = split(/\s+/, $_, 0); push @{$r{join ' ' x 8, @F[0..3]};}, [@F[4, 6]]; sub END { foreach $k (keys %r) { my($x, $y); map {$x += $$_[0]; $y += $$_[1];} @{$r{$k};}; my @g = split(/\s+/,$k); print OUT "$g[0]\t@g[1]\t@g[2]\t@g[3]\t", $x / scalar(@{$r +{$k};}), "\t$y\n"; } } }

Another odd thing to note about this code is the  END block planted in the middle of it, written in a disparaged way as a sub block. Please see the "BEGIN, UNITCHECK, CHECK, INIT and END" section in perlmod. Because all  END blocks run at the end (!) of all other code, I think this chunk of code could more clearly and conventionally be written as:

while (<IN>) { our(@F) = split(/\s+/, $_, 0); push @{$r{join ' ' x 8, @F[0..3]};}, [@F[4, 6]]; } ... all other code ... END { foreach $k (keys %r) { my($x, $y); map {$x += $$_[0]; $y += $$_[1];} @{$r{$k};}; my @g = split(/\s+/,$k); print OUT "$g[0]\t@g[1]\t@g[2]\t@g[3]\t", $x / scalar(@{$r{$k} +;}), "\t$y\n"; } }
Good luck.


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^2: Code clarification - use of map and $$_
by pryrt (Abbot) on Aug 09, 2016 at 15:16 UTC

    ++AnomalousMonk: that helped (me, anyway; don't know about the OP). That was my first guess, but my initial experiments with the OP code didn't mesh. But I later saw that the print went to OUT, and forgot to redo a test to STDOUT. Thus I started thinking that it was a sub named END in a bout of horrible style. But I think you're right, it's an END block.

    However, with this simplified code, I still only see the FIRST instance of the END block doing anything:

    use strict; use warnings; $, = ","; $\ = "\n"; $" = ";"; my %r = ( 0 => 0, 1 => 0, 2 => 0, 3 => 0 ); foreach (1..10) { my $x = $_ % 4; ++$r{$x}; sub END { print __LINE__, "sub END block", $x, $r{$x} }; } foreach(1 .. 10) { my $x = $_ % 4; print "$_ => $x => $r{$x}"}; print __LINE__, "END OF SCRIPT"; __END__ __OUTPUT__ 1 => 1 => 3 2 => 2 => 3 3 => 3 => 2 4 => 0 => 2 5 => 1 => 3 6 => 2 => 3 7 => 3 => 2 8 => 0 => 2 9 => 1 => 3 10 => 2 => 3 17,END OF SCRIPT 13,sub END block,1,3
      ... I still only see the FIRST instance of the END block doing anything ...

      From this I think you've already gotten the point, but anyway... There is only one instance of any given  END block in a program:

      c:\@Work\Perl\monks>perl -wMstrict -le "for my $str (qw(one two three)) { print qq{in for loop: '$str'}; END { print 'END block ONE'; } END { print 'END block TWO'; } END { print 'END block THREE'; } } " in for loop: 'one' in for loop: 'two' in for loop: 'three' END block THREE END block TWO END block ONE


      Give a man a fish:  <%-{-{-{-<

      Oops, re-reading AnomalousMonk's post and the OP, I was reminded that there was a loop inside the END block, and that does what was intended.

      use strict; use warnings; $, = ","; $\ = "\n"; $" = ";"; my %r = ( 0 => 0, 1 => 0, 2 => 0, 3 => 0 ); foreach (1..10) { my $x = $_ % 4; ++$r{$x}; sub END { $, = " => "; foreach my $k ( keys %r ) { print __LINE__, "sub END block with k", $k, $r{$k} } }; } foreach(1 .. 10) { my $x = $_ % 4; print "$_ => $x => $r{$x}"}; print __LINE__, "END OF SCRIPT"; __END__ __OUTPUT__ 1 => 1 => 3 2 => 2 => 3 3 => 3 => 2 4 => 0 => 2 5 => 1 => 3 6 => 2 => 3 7 => 3 => 2 8 => 0 => 2 9 => 1 => 3 10 => 2 => 3 22,END OF SCRIPT 16 => sub END block with k => 0 => 2 16 => sub END block with k => 1 => 3 16 => sub END block with k => 3 => 2 16 => sub END block with k => 2 => 3