Iterator special variable $_

Iterator special variable $_

am 07.01.2007 23:04:19 von markhobley

The iterator special variable can be used in a foreach loop as follows:

@fruit = ( "apples", "bananas", "cherries" );
foreach (@fruit) {
print "I like $_\n";
}

Is it accepted to use the special variable in a for loop as follows?

use strict;
use warnings;
for ($_=0; $_ <=9; $_++) {
print "$_\n";
}

(The above works and I get no errors.)

Would you expect nested loops using the iterator variable to work?

use strict;
use warnings;
for ($_=0; $_<=3; $_++) {
print "Loop $_\n";
for ($_=0; $_<=6; $_++) {
print "Value $_\n";
}
}

(The above does not work, but I get no warnings)

Could I fix these loops to work by changing variable scope?

Is it valid to change the scope of special variables?

Is the observed behaviour above undefined, or is there a document clarifying
this somewhere?


Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/

Re: Iterator special variable $_

am 07.01.2007 23:16:13 von Paul Lalli

Mark Hobley wrote:
> Is it accepted to use the special variable in a for loop as follows?
>
> use strict;
> use warnings;
> for ($_=0; $_ <=9; $_++) {
> print "$_\n";
> }
>
> (The above works and I get no errors.)

If by "accepted" you mean "does it work", then as you discovered, yes.
If, however, you mean "is this a good idea", the answer is no. Why
would you do that? What reason would you have to use a default
variable in that manner? In general, $_ should never be assigned to.
It's an implicit variable, and should be used as such. Declare a
counter variable if you need it for some reason, or just use a foreach
loop like $_ was designed to be used:

for (0..9) {
print "$_\n";
}

>
> Would you expect nested loops using the iterator variable to work?
>
> use strict;
> use warnings;
> for ($_=0; $_<=3; $_++) {
> print "Loop $_\n";
> for ($_=0; $_<=6; $_++) {
> print "Value $_\n";
> }
> }
>
> (The above does not work, but I get no warnings)

Odd, the above code works perfectly for me. It first assigns $_ to 0
and prints out the first print statement. Then it assigns $_ to 0
(again), and prints the inner loop's statement. Then it goes through
the inner loop, ending when $_ is set to 7, which is not less than or
equal to 6. Then it goes back up to the condition of the first loop,
sees that $_ is now greater than 3, and the first loop exits.

What were you expecting it to do?

> Could I fix these loops to work by changing variable scope?

I have no idea what "fix" you're planning on making - the above code
does exactly what it should do.

> Is it valid to change the scope of special variables?\

You cannot make a lexical variable named $_, if that's what you mean.
You can, however, localize $_, at the start of each loop. That would
result in the 0..6 loop printing out four times. Is that what you
want?

> Is the observed behaviour above undefined, or is there a document clarifying
> this somewhere?

The above behavior is exactly what I expect it to be. If it's not what
you expect it to be, you'll have to explain what you expect. It's
"defined" in that it's completely non-ambiguous...

Paul Lalli

Re: Iterator special variable $_

am 07.01.2007 23:16:13 von Paul Lalli

Mark Hobley wrote:
> Is it accepted to use the special variable in a for loop as follows?
>
> use strict;
> use warnings;
> for ($_=0; $_ <=9; $_++) {
> print "$_\n";
> }
>
> (The above works and I get no errors.)

If by "accepted" you mean "does it work", then as you discovered, yes.
If, however, you mean "is this a good idea", the answer is no. Why
would you do that? What reason would you have to use a default
variable in that manner? In general, $_ should never be assigned to.
It's an implicit variable, and should be used as such. Declare a
counter variable if you need it for some reason, or just use a foreach
loop like $_ was designed to be used:

for (0..9) {
print "$_\n";
}

>
> Would you expect nested loops using the iterator variable to work?
>
> use strict;
> use warnings;
> for ($_=0; $_<=3; $_++) {
> print "Loop $_\n";
> for ($_=0; $_<=6; $_++) {
> print "Value $_\n";
> }
> }
>
> (The above does not work, but I get no warnings)

Odd, the above code works perfectly for me. It first assigns $_ to 0
and prints out the first print statement. Then it assigns $_ to 0
(again), and prints the inner loop's statement. Then it goes through
the inner loop, ending when $_ is set to 7, which is not less than or
equal to 6. Then it goes back up to the condition of the first loop,
sees that $_ is now greater than 3, and the first loop exits.

What were you expecting it to do?

> Could I fix these loops to work by changing variable scope?

I have no idea what "fix" you're planning on making - the above code
does exactly what it should do.

> Is it valid to change the scope of special variables?\

You cannot make a lexical variable named $_, if that's what you mean.
You can, however, localize $_, at the start of each loop. That would
result in the 0..6 loop printing out four times. Is that what you
want?

> Is the observed behaviour above undefined, or is there a document clarifying
> this somewhere?

The above behavior is exactly what I expect it to be. If it's not what
you expect it to be, you'll have to explain what you expect. It's
"defined" in that it's completely non-ambiguous...

Paul Lalli

Re: Iterator special variable $_

am 07.01.2007 23:23:44 von Gunnar Hjalmarsson

Mark Hobley wrote:
> Would you expect nested loops using the iterator variable to work?

Yes, if you localize it.

> use strict;
> use warnings;
> for ($_=0; $_<=3; $_++) {

for (local $_ = 0; $_<=3; $_++) {

> print "Loop $_\n";
> for ($_=0; $_<=6; $_++) {

for (local $_=0; $_<=6; $_++) {

> print "Value $_\n";
> }
> }

But this would be a more readable and Perlish solution IMO:

foreach my $loop ( 0..3 ) {
print "Loop $loop\n";
foreach my $val ( 0..6 ) {
print "Value $val\n";
}
}

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: Iterator special variable $_

am 07.01.2007 23:23:44 von Gunnar Hjalmarsson

Mark Hobley wrote:
> Would you expect nested loops using the iterator variable to work?

Yes, if you localize it.

> use strict;
> use warnings;
> for ($_=0; $_<=3; $_++) {

for (local $_ = 0; $_<=3; $_++) {

> print "Loop $_\n";
> for ($_=0; $_<=6; $_++) {

for (local $_=0; $_<=6; $_++) {

> print "Value $_\n";
> }
> }

But this would be a more readable and Perlish solution IMO:

foreach my $loop ( 0..3 ) {
print "Loop $loop\n";
foreach my $val ( 0..6 ) {
print "Value $val\n";
}
}

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: Iterator special variable $_

am 08.01.2007 00:31:57 von Uri Guttman

>>>>> "MH" == Mark Hobley writes:

MH> The iterator special variable can be used in a foreach loop as follows:

it is not the 'iterator' variable. a better name is the default
variable. it is used in many functions as the default argument, for some
i/o ops, regexes, etc.

my rule is to avoid $_ in general as i prefer named variables
(preferably lexicals) as they document the code better. i only use $_
when there is no other choice (map/grep) or where is provides a distinct
advantage (e.g. see Sort::Maker which uses it to pass in the records in $_
for key extraction).

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Re: Iterator special variable $_

am 08.01.2007 00:31:57 von Uri Guttman

>>>>> "MH" == Mark Hobley writes:

MH> The iterator special variable can be used in a foreach loop as follows:

it is not the 'iterator' variable. a better name is the default
variable. it is used in many functions as the default argument, for some
i/o ops, regexes, etc.

my rule is to avoid $_ in general as i prefer named variables
(preferably lexicals) as they document the code better. i only use $_
when there is no other choice (map/grep) or where is provides a distinct
advantage (e.g. see Sort::Maker which uses it to pass in the records in $_
for key extraction).

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Re: Iterator special variable $_

am 08.01.2007 02:04:19 von markhobley

In alt.perl Gunnar Hjalmarsson wrote:

> foreach my $loop ( 0..3 ) {

Ok, that is clever, but what if I wanted 1 to 50000?
Wouldn't that generate 50000 temporary values in memory to feed the loop, as
opposed to just one value iterating 50000 times?

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/

Re: Iterator special variable $_

am 08.01.2007 02:04:19 von markhobley

In alt.perl Gunnar Hjalmarsson wrote:

> foreach my $loop ( 0..3 ) {

Ok, that is clever, but what if I wanted 1 to 50000?
Wouldn't that generate 50000 temporary values in memory to feed the loop, as
opposed to just one value iterating 50000 times?

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/

Re: Iterator special variable $_

am 08.01.2007 02:04:19 von markhobley

In alt.perl Paul Lalli wrote:

> What were you expecting it to do?

I was expecting a nested loop with the inner iterator not affecting the outer
loop, ie the inner iterator scope is local to the inner loop.

Having done some googling, it appears that nesting a foreach loop would have
worked in the expected manner, because the iterator is preserved on entry and
exit from the loop, but this does not happen with a for loop.

> You can, however, localize $_, at the start of each loop.

Ok. Thanks for the input.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/

Re: Iterator special variable $_

am 08.01.2007 02:04:19 von markhobley

In alt.perl Paul Lalli wrote:

> What were you expecting it to do?

I was expecting a nested loop with the inner iterator not affecting the outer
loop, ie the inner iterator scope is local to the inner loop.

Having done some googling, it appears that nesting a foreach loop would have
worked in the expected manner, because the iterator is preserved on entry and
exit from the loop, but this does not happen with a for loop.

> You can, however, localize $_, at the start of each loop.

Ok. Thanks for the input.

Regards,

Mark.

--
Mark Hobley
393 Quinton Road West
QUINTON
Birmingham
B32 1QE

Telephone: (0121) 247 1596
International: 0044 121 247 1596

Email: markhobley at hotpop dot donottypethisbit com

http://markhobley.yi.org/

Re: Iterator special variable $_

am 08.01.2007 02:28:34 von jwkenne

Mark Hobley wrote:
> In alt.perl Gunnar Hjalmarsson wrote:
>
>> foreach my $loop ( 0..3 ) {
>
> Ok, that is clever, but what if I wanted 1 to 50000?
> Wouldn't that generate 50000 temporary values in memory to feed the loop, as
> opposed to just one value iterating 50000 times?

Theoretically, yes, but, in practice, perl has been smart enough not to
do that for ages.

--
John W. Kennedy
"The blind rulers of Logres
Nourished the land on a fallacy of rational virtue."
-- Charles Williams. "Taliessin through Logres: Prelude"

Re: Iterator special variable $_

am 08.01.2007 02:28:34 von jwkenne

Mark Hobley wrote:
> In alt.perl Gunnar Hjalmarsson wrote:
>
>> foreach my $loop ( 0..3 ) {
>
> Ok, that is clever, but what if I wanted 1 to 50000?
> Wouldn't that generate 50000 temporary values in memory to feed the loop, as
> opposed to just one value iterating 50000 times?

Theoretically, yes, but, in practice, perl has been smart enough not to
do that for ages.

--
John W. Kennedy
"The blind rulers of Logres
Nourished the land on a fallacy of rational virtue."
-- Charles Williams. "Taliessin through Logres: Prelude"

Re: Iterator special variable $_

am 08.01.2007 02:33:44 von jurgenex

Mark Hobley wrote:
> Having done some googling, it appears that nesting a foreach loop
> would have worked in the expected manner, because the iterator is
> preserved on entry and exit from the loop, but this does not happen
> with a for loop.

You are mistaken. From "perldoc perlsyn":
The "foreach" keyword is actually a synonym for the "for" keyword, so
you can use "foreach" for readability or "for" for brevity.

jue

Re: Iterator special variable $_

am 08.01.2007 02:33:44 von jurgenex

Mark Hobley wrote:
> Having done some googling, it appears that nesting a foreach loop
> would have worked in the expected manner, because the iterator is
> preserved on entry and exit from the loop, but this does not happen
> with a for loop.

You are mistaken. From "perldoc perlsyn":
The "foreach" keyword is actually a synonym for the "for" keyword, so
you can use "foreach" for readability or "for" for brevity.

jue

Re: Iterator special variable $_

am 08.01.2007 03:06:14 von Gunnar Hjalmarsson

Jürgen Exner wrote:
> Mark Hobley wrote:
>>Having done some googling, it appears that nesting a foreach loop
>>would have worked in the expected manner, because the iterator is
>>preserved on entry and exit from the loop, but this does not happen
>>with a for loop.
>
> You are mistaken.

Don't think so.

> From "perldoc perlsyn":
> The "foreach" keyword is actually a synonym for the "for" keyword, so
> you can use "foreach" for readability or "for" for brevity.

A foreach loop is a foreach loop no matter which keyword you use.

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: Iterator special variable $_

am 08.01.2007 03:06:14 von Gunnar Hjalmarsson

Jürgen Exner wrote:
> Mark Hobley wrote:
>>Having done some googling, it appears that nesting a foreach loop
>>would have worked in the expected manner, because the iterator is
>>preserved on entry and exit from the loop, but this does not happen
>>with a for loop.
>
> You are mistaken.

Don't think so.

> From "perldoc perlsyn":
> The "foreach" keyword is actually a synonym for the "for" keyword, so
> you can use "foreach" for readability or "for" for brevity.

A foreach loop is a foreach loop no matter which keyword you use.

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: Iterator special variable $_

am 08.01.2007 03:24:12 von Uri Guttman

>>>>> "JE" == J.AN|rgen Exner writes:

JE> Mark Hobley wrote:
>> Having done some googling, it appears that nesting a foreach loop
>> would have worked in the expected manner, because the iterator is
>> preserved on entry and exit from the loop, but this does not happen
>> with a for loop.

JE> You are mistaken. From "perldoc perlsyn":
JE> The "foreach" keyword is actually a synonym for the "for" keyword, so
JE> you can use "foreach" for readability or "for" for brevity.

i think he means the difference between the foreach loop (over a list) and
the c style for loop. perlsyn states that the foreach loop variable is
localized unless it is declared right there with my. this happens for
named or $_. the c style for loop doesn't do anything and you have to
localize or use my vars yourself (even for $_).

The "foreach" loop iterates over a normal list value and sets the vari$B!>(B
able 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$B!G(Bs still localized to
the loop. This implicit localisation occurs only in a "foreach" loop.

now on top of that, you can use 'for' OR 'foreach' for either style of
loop. it is what is inside the () that actually determines the loop
style. the docs seem to use 'foreach' for the list loop and 'for' for
the c style loop. i do the same thing (but i RARELY use c style for
loops).

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Re: Iterator special variable $_

am 08.01.2007 03:24:12 von Uri Guttman

>>>>> "JE" == J.AN|rgen Exner writes:

JE> Mark Hobley wrote:
>> Having done some googling, it appears that nesting a foreach loop
>> would have worked in the expected manner, because the iterator is
>> preserved on entry and exit from the loop, but this does not happen
>> with a for loop.

JE> You are mistaken. From "perldoc perlsyn":
JE> The "foreach" keyword is actually a synonym for the "for" keyword, so
JE> you can use "foreach" for readability or "for" for brevity.

i think he means the difference between the foreach loop (over a list) and
the c style for loop. perlsyn states that the foreach loop variable is
localized unless it is declared right there with my. this happens for
named or $_. the c style for loop doesn't do anything and you have to
localize or use my vars yourself (even for $_).

The "foreach" loop iterates over a normal list value and sets the vari$B!>(B
able 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$B!G(Bs still localized to
the loop. This implicit localisation occurs only in a "foreach" loop.

now on top of that, you can use 'for' OR 'foreach' for either style of
loop. it is what is inside the () that actually determines the loop
style. the docs seem to use 'foreach' for the list loop and 'for' for
the c style loop. i do the same thing (but i RARELY use c style for
loops).

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Re: Iterator special variable $_

am 10.01.2007 01:53:22 von Verizon

"Mark Hobley" wrote in message
news:506874-jua.ln1@neptune.markhobley.yi.org...
> Would you expect nested loops using the iterator variable to work?
>
> use strict;
> use warnings;
> for ($_=0; $_<=3; $_++) {
> print "Loop $_\n";
> for ($_=0; $_<=6; $_++) {
> print "Value $_\n";
> }
> }

What you seem to want here is something like:

for(0..3)
{
print "Loop 0: $_\n" ;
for(0..6) # Perl automatically localizes $_, but now you can't see
the count for the outer loop
{
print "Loop 1: $_\n" ;
}
}

Perl will localize the scope of $_ for you and the $_ of the outer loop will
be maintained. $_ should not be thought of as an iterator, although it can
contain the value associated with one.

If you assign things to $_ all bets are off. You should avoid assigning to
the default variable ($_) - think of it as a global read-mostly even though
it isn't necessarily global and there are many cases where you will want to
modify it, such as in substitutions. "Never" is probably more appropriate
than "should", but "never" has its limitations too and Perl lets you do all
sorts of things that you shouldn't - that is why we love it so much!

If you need to be able to use the iterator from the outer loop within the
inner loop, you're better off assigning it to a local variable. In this
case you can do it the usual Perl way or use your iterator expression:

foreach my $outer (0..3) # or: for (my $outer = 0 ; $outer < 4 ;
$outer++)
{
print "Loop 0: $outer\n" ;
foreach my $inner (0..6) # etc.
{
print "Loop 1: $outer/$inner\n" ;
}
}

Craig Arnold

Re: Iterator special variable $_

am 10.01.2007 01:53:22 von Verizon

"Mark Hobley" wrote in message
news:506874-jua.ln1@neptune.markhobley.yi.org...
> Would you expect nested loops using the iterator variable to work?
>
> use strict;
> use warnings;
> for ($_=0; $_<=3; $_++) {
> print "Loop $_\n";
> for ($_=0; $_<=6; $_++) {
> print "Value $_\n";
> }
> }

What you seem to want here is something like:

for(0..3)
{
print "Loop 0: $_\n" ;
for(0..6) # Perl automatically localizes $_, but now you can't see
the count for the outer loop
{
print "Loop 1: $_\n" ;
}
}

Perl will localize the scope of $_ for you and the $_ of the outer loop will
be maintained. $_ should not be thought of as an iterator, although it can
contain the value associated with one.

If you assign things to $_ all bets are off. You should avoid assigning to
the default variable ($_) - think of it as a global read-mostly even though
it isn't necessarily global and there are many cases where you will want to
modify it, such as in substitutions. "Never" is probably more appropriate
than "should", but "never" has its limitations too and Perl lets you do all
sorts of things that you shouldn't - that is why we love it so much!

If you need to be able to use the iterator from the outer loop within the
inner loop, you're better off assigning it to a local variable. In this
case you can do it the usual Perl way or use your iterator expression:

foreach my $outer (0..3) # or: for (my $outer = 0 ; $outer < 4 ;
$outer++)
{
print "Loop 0: $outer\n" ;
foreach my $inner (0..6) # etc.
{
print "Loop 1: $outer/$inner\n" ;
}
}

Craig Arnold