grep example's use of $_ confusing me.

J

Justin C

I'm reading The Alpaca (Intermediate Perl - yeah, I know, do I *really*
think I'm smart enough to be there yet?) and in Chapter 6 I find the
following example:

my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
my @indices_of_odd_digit_sums = grep {
my $number = $input_numbers[$_];
my $sum;
$sum += $_ for split //, $number;
$sum % 2;
} 0..$#input_numbers;

What has happened to $_ ? In line three I understand that it is one of
the indices of @input_numbers, but in line 5 it has become each of the
digits of @input_numbers. I'm just getting used to map and grep, and
throwing that in there has been a bit confusing. I can see what has
happened, but am having difficulty reconciling that with use of $_ in
grep and map blocks. Is the first $_ clobbered, or is it still there
after the 5th line? ... hmmm, yes it is... not it isn't it's been
clobbered, it's... no, I was right the first time! (it's been a long
week). So, is line 5 a naked block with it's own $_? How do I identify,
in other grep/map blocks, which $_ is $_?!

Justin.
 
J

Jim Gibson

Justin C said:
I'm reading The Alpaca (Intermediate Perl - yeah, I know, do I *really*
think I'm smart enough to be there yet?) and in Chapter 6 I find the
following example:

my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
my @indices_of_odd_digit_sums = grep {
my $number = $input_numbers[$_];
my $sum;
$sum += $_ for split //, $number;
$sum % 2;
} 0..$#input_numbers;

What has happened to $_ ? In line three I understand that it is one of
the indices of @input_numbers, but in line 5 it has become each of the
digits of @input_numbers.

The 'for' in line 5 is a statement modifier. Search for 'Statement
Modifiers' in perldoc perlsyn. Line 5 is equivalent to:

foreach ( split //, $number ) {
$sum += $_;
}

Further on in 'perldoc perlsyn' we read that:

"Foreach Loops

The "foreach" loop iterates over a normal list value and sets the
variable VAR to be each element of the list in turn. If the variable
is preceded with the keyword "my", then it is lexically scoped, and is
therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my", it uses
that variable instead of the global one, but it's still localized to
the loop. This implicit localisation occurs only in a "foreach" loop."

Thus, $_ is localized in line 5 and regains its previous value at line
6.

Note also that the original value of $_ at entering the grep block is
only used once in the first line of the block, so it doesn't really
matter whether $_ is clobbered by the for modifier. Programming that
does not depend upon little-known behavior is usually a "good thing".
I'm just getting used to map and grep, and
throwing that in there has been a bit confusing. I can see what has
happened, but am having difficulty reconciling that with use of $_ in
grep and map blocks. Is the first $_ clobbered, or is it still there
after the 5th line? ... hmmm, yes it is... not it isn't it's been
clobbered, it's... no, I was right the first time! (it's been a long
week). So, is line 5 a naked block with it's own $_? How do I identify,
in other grep/map blocks, which $_ is $_?!

If you want to know what value is in $_ at any point in your program,
run it with a debugger or add some print statements:

#!/usr/bin/perl

use strict;
use warnings;

my @input_numbers = (1, 2, 4, 8, 16, 32, 64);
my @indices_of_odd_digit_sums = grep {
print "1: \$_=$_\n";
my $number = $input_numbers[$_];
my $sum;
$sum += $_ for split //, $number;
print "2: \$_=$_\n";
$sum % 2;
} 0..$#input_numbers;

print "Indices of odd digit sums: ", join(", ",
@indices_of_odd_digit_sums),
"\n";

__OUTPUT__

1: $_=0
2: $_=0
1: $_=1
2: $_=1
1: $_=2
2: $_=2
1: $_=3
2: $_=3
1: $_=4
2: $_=4
1: $_=5
2: $_=5
1: $_=6
2: $_=6
Indices of odd digit sums: 0, 4, 5
 
J

Justin C

I'm reading The Alpaca (Intermediate Perl - yeah, I know, do I *really*
think I'm smart enough to be there yet?) and in Chapter 6 I find the
following example:

Thanks, Tad and Jim. Things are clearer now.

Justin.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top