Popcorn Dave has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

While perusing some perl code in 2600 magazine ( which the author said was perhaps crude ) I came across a section where he used:

for ($i=1; $i <= @ARGV; $$i++)

and I thought, why not do:

<P> $count = @ARGV; for (1..$count)

So my question is: Is there any advantage to doing the code my way? I think mine is a bit more readable, but is it any more efficient?

Some people fall from grace. I prefer a running start...

Replies are listed 'Best First'.
Re: for ( ; ; ) vs for ( .. )
by broquaint (Abbot) on May 23, 2002 at 16:37 UTC
    Iterating through a list is more efficient than looping over an index variable. This is because all the index keeping is done internally, where as the index variable solution has to do a lot of external operations (see. more CPU time).

    Also you can't accidentally offset the index within the iterative code e.g

    for(my $i = 0; $i < @ARGVl $i++) { if($ARGV[$i] =~ /meets some condition/) { # ack! the index has been offset $i += 2; } }
    Compared to
    for my $i (0 .. $#ARGV) { if($ARGV[$i] =~ /meets some condition/) { # doesn't matter as $i will be set again in the next iteration $i += 2; } }
    This works both ways however as you may want to intentionally affect the offset, but you're possibly better off using a while loop in the first place.

    Here's a quick benchmark for those in need of speed

    use Benchmark qw(cmpthese); my @list = 1..10000; my $r; cmpthese(-10, { cstyle => sub { for(my $i = 0; $i < @list; $i++) { $r = $list[$i]; } }, perlstyle => sub { for my $i (@list) { $r = $i; } } }); __output__ Benchmark: running cstyle, perlstyle, each for at least 10 CPU seconds +... cstyle: 15 wallclock secs (10.57 usr + 0.05 sys = 10.62 CPU) @ 36 +.06/s (n=383) perlstyle: 15 wallclock secs (10.10 usr + 0.03 sys = 10.13 CPU) @ 86 +.77/s (n=879) Rate cstyle perlstyle cstyle 36.1/s -- -58% perlstyle 86.8/s 141% --

    HTH

    _________
    broquaint

    update: added benchmark because it's just so darned easy

(jeffa) Re: for ( ; ; ) vs for ( .. )
by jeffa (Bishop) on May 23, 2002 at 16:43 UTC
    Ask Dr. Benchmark ;)
    use strict; use Benchmark; timethese(10, { 'c-style' => sub { for (my $i = 0; $i < 1_000_000; $i++) { } }, 'list style' => sub { for my $i (0..1_000_000) { } }, });

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: for ( ; ; ) vs for ( .. )
by Elian (Parson) on May 23, 2002 at 17:16 UTC
    If you're using an older version of perl (before 5.005) the for(;;) way is more memory efficient, since it doesn't build a temporary list of integers from the start to end of your range.
      Am I correct in understanding that the three argument for is actually converted into a while continue? With the added overhead of two scoped blocks?

      Yves / DeMerphq
      ---
      Writing a good benchmark isnt as easy as it might look.

        B::Deparse is your friend here.
        $ perl -MO=Deparse -e 'for ($x = 0; $x < 10; $x++) {}' $x = 0; while ($x < 10) { (); } continue { ++$x }
        So the answer would be yes. As to whether there's extra scope overhead, well, we'll leave that as an exercise for the reader.
Re: for ( ; ; ) vs for ( .. )
by Joost (Canon) on May 23, 2002 at 16:33 UTC
    Actually, why not:
    for (@ARGV) { .. }
    -- Joost downtime n. The period during which a system is error-free and immune from user input.
      Perhaps because its just not the same thing? Your's sets $_ to the elements of the array, while Popcorn Dave's sets $_ to one more than the indices of the array (which probably isn't the desired result). As broquaint suggests, I tend to use the for(0..$#ARGV) version if I happen to need the indices.

      --
      I'd like to be able to assign to an luser

      In the original code, the first argument was an option, the rest were files, so that wouldn't have worked in this particular instance.

      Some people fall from grace. I prefer a running start...