On "for (@foo)"

P

Paul Lalli

for my $i (reverse (1..20)){
do_stuff_with($i);
}

This, of course, assumes that:

* 20 is a small number[1] because the optomisation of .. in for()
does not cope with reverse().

* do_stuff_with() does not alter its arguments. If it did I'd still
not use a C-style for, I'd use a while().

[1] er, 20 _is_ a small number but you know what I mean. :)

I never claimed that this was a *good* way of doing it. I merely
commented that for ($i=20; $i>0; $i--) {} could be written without using
the C-style for loop.

Paul Lalli
 
B

Brian McCauley

Paul Lalli said:
I never claimed that this was a *good* way of doing it. I merely
commented that for ($i=20; $i>0; $i--) {} could be written without using
the C-style for loop.

Well I do claim that reverse(1..20) is a good way of doing it. I just
think it is worth warning people that it's only good for small numbers
of interations.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
P

Paul Lalli

Ben Morrow said:
You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

Ben

You do if you want to skip some elements:

Jim 53% cat loops.pl
#!/usr/local/bin/perl
use strict;
use warnings;

my @array = ( 0..4 );

print "C-style:\n";
for( my $i = 0; $i < @array; $i++ ) {
print "$i. $array[$i]\n";
$i++ if $i == 2;
}

print "Perlish:\n";
for my $i ( 0 .. $#array ) {
print "$i. $array[$i]\n";
$i++ if $i == 2;
}

Ew. Why would you ever do that? In either of those loops? Incrementing
the count variable within a Cstyle loop is just terrible.

for (my $i=0; $i<@array; $i++){
next if $i == 2;
print "$i, $array[$i]\n";
}

for my $i (0..$#array){
next if $i == 2;
print "$i, $array[$i]\n";
}


Paul Lalli
 
B

Brian McCauley

Paul Lalli said:
for( my $i = 0; $i < @array; $i++ ) {
print "$i. $array[$i]\n";
$i++ if $i == 2;
}
Ew. Why would you ever do that? In either of those loops? Incrementing
the count variable within a Cstyle loop is just terrible.

Yeah verily! The c-style loop is just a shorthand for a while loop,
you you are going to be manipulating the loop control variable
anywhere other than in the for(;;) it's better IMNSHO to write out the
while loop long hand.
next if $i == 2;

It is also common in a c-style loop to decrement the counter in order
to redo the current element but Perl has an explicit redo command.

my %redo = ( 2 => 2 );
for my $i ( 0 .. 10 ) {
print "$i ";
if ( $redo{$i} ) {
$redo{$i}--;
redo;
}
}
__END__
0 1 2 2 2 3 4 5 6 7 8 9 10
 
B

Ben Morrow

Quoth Jim Gibson said:
Ben Morrow said:
Quoth "Andrew Palmer said:
OK, now, in an expression like this

for my $x (@X) {
# etc.
}

I assume that Perl keeps track of the index on @X correponding to
the current element. Is there a way to access this "current index"
from within a Perl program?

I think the only way to do what you want is like

for(my $i=0;$i<$#X;++$i)
{
$X[$i]=0;
}

You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

Ben

You do if you want to skip some elements:

Jim 53% cat loops.pl
#!/usr/local/bin/perl
use strict;
use warnings;

my @array = ( 0..4 );

print "C-style:\n";
for( my $i = 0; $i < @array; $i++ ) {
print "$i. $array[$i]\n";
$i++ if $i == 2;
}

print "Perlish:\n";
for my $i ( 0 .. $#array ) {

next if $i == 3;
print "$i. $array[$i]\n";
$i++ if $i == 2;
}

Ben
 
A

Anno Siegel

Jim Gibson said:
[...]
[...]

Here is a short program demonstrating this technique. If anyone has a
better way of doing this, please post it.

Jim 52% cat showopts.pl
#!/usr/local/bin/perl
use strict;
use warnings;

my $debug = 0;
my $output = 0;
my $output_file = 'default.out';

for( my $i = 0; $i < @ARGV; $i++ ) {
my $arg = $ARGV[$i];
if( $arg eq '-d' ) {
$debug = 1;
}elsif( $arg eq '-o' ) {
$output = 1;
if( $i < $#ARGV && $ARGV[$i+1] !~ /^-/ ) {
$output_file = $ARGV[++$i];
}
}
}

A while-loop works just as well without indexing:

while ( @ARGV ) {
my $arg = shift;
if( $arg eq '-d' ) {
$debug = 1;
} elsif ( $arg eq '-o' ) {
$output = 1;
if ( @ARGV && $ARGV[ 0] ) {
$output_file = shift;
}
}
}

Anno
 
D

David H. Adler

You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

"Never"?

How about:

for ($i = 20; $i > 0; $i--) {
do_stuff_with($i);
}

for my $i (reverse (1..20)){
do_stuff_with($i);
}
(and, although I'm sure someone will come up with a way of avoiding the
c-style loop there, I'm not sure it'll be more readable)


I disagree. <shrug>

Ok, here you got me. I should have stuck with my original thought
of using $i - 3 instad of $i-- ...

Really, my disagreement was with the, IMO, extreme "never". I'd be
happy with "extremely rarely". :)

dha
 
P

Paul Lalli

Ok, here you got me. I should have stuck with my original thought
of using $i - 3 instad of $i-- ...

for my $i (grep { ($_ + 1) % 3 == 0 } reverse (1..20) ) {
do_stuff_with($i);
}
Really, my disagreement was with the, IMO, extreme "never". I'd be
happy with "extremely rarely". :)

At this point, I'm mostly joking. I would never actually write code like
the above. I'm just not convinced there's any variation of a C-style for
loop that cannot be emulated with a Perl-style foreach loop.

Paul Lalli
 
D

David H. Adler

for my $i (grep { ($_ + 1) % 3 == 0 } reverse (1..20) ) {
do_stuff_with($i);
}


At this point, I'm mostly joking. I would never actually write code like
the above.

Oh thank $deity! :)
I'm just not convinced there's any variation of a C-style for loop
that cannot be emulated with a Perl-style foreach loop.

I'm sure you're right, but I'm not convinced it's always a good idea.

Thinking about it further, I think in some cases using the c-style may
be good in the sense that it isolates the loop logic from what's going
on inside the loop - which might work with one's brain better. I. e.
sort of the way that templating systems separate content from code
(probably only sort of). But, this being perl, YMMVExtrordinarily.

dha

--
David H. Adler - <[email protected]> - http://www.panix.com/~dha/
With its concern for ethics and its snooty disdain for digging up
corpses, killing test subjects, and resurrecting the dead, the medical
establishment has lost ground to mad scientists in such important fields
as zombie creation. - The Onion, Volume 38 Issue 36
 
P

P Buder

Paul Lalli said:
I'm just not convinced there's any variation of a C-style for
loop that cannot be emulated with a Perl-style foreach loop.

My usual use for a C style loop is when I want to know where the loop
exited.

for $i(0..4)
{
last if # some condition, let's say $i==2 just before loop exit.
}
# Here $i is undef which isn't what I want.

Compared to C style

for($i=0; $i<=4; $i++)
{
last if # some condition, let's say $i==2 just before loop exit.
}
# Here $i == 2 which is what I want.

Of course you could assign $i's value to something else in the
first chunk but that seems messier.
 
B

Ben Morrow

[your newsreader seems to be putting 80 spaces on every blank line,
which is unnecessary to say the least...]

Quoth P Buder said:
My usual use for a C style loop is when I want to know where the loop
exited.

for $i(0..4)
{
last if # some condition, let's say $i==2 just before loop exit.
}
# Here $i is undef which isn't what I want.

Compared to C style

for($i=0; $i<=4; $i++)
{
last if # some condition, let's say $i==2 just before loop exit.
}
# Here $i == 2 which is what I want.

Neither of these work under 'use strict'. In the case of the C-style
loop

for (my $i = 0; $i <= 4; $i++) {

the variable is scoped to all iterations as one scope rather than each
iter separately; it still isn't visible outside. If you want it to be,
you lose the only minor advantage a C-style for has over the equivalent
while---that it introduces this extra scope---so you should use while
instead:

my $i = 0;
while ($i <= 4) {
...
last if ...;
}
continue { $i++ }

Ben
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top