Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > grep example's use of $_ confusing me.

Reply
Thread Tools

grep example's use of $_ confusing me.

 
 
Justin C
Guest
Posts: n/a
 
      10-29-2010
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.

--
Justin C, by the sea.
 
Reply With Quote
 
 
 
 
Jim Gibson
Guest
Posts: n/a
 
      10-29-2010
In article <u6erp7->, Justin C
<> wrote:

> 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

--
Jim Gibson
 
Reply With Quote
 
 
 
 
Justin C
Guest
Posts: n/a
 
      11-01-2010
On 2010-10-29, Justin C <> wrote:
> 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.

--
Justin C, by the sea.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Confusing docs . . . how do I use gcd2? Matt Ruby 6 01-10-2010 03:45 AM
How should I use grep from python? Matthew Wilson Python 5 05-07-2009 01:55 PM
Want to use equivalent of grep function in perl perlmbk Perl Misc 3 11-10-2005 12:20 PM
How do I use grep with the Shell class Mark Wilson Ruby 2 09-17-2003 09:29 PM
Pattern matching help! grep emails from file! danpres2k Perl 3 08-25-2003 02:47 PM



Advertisments