in reply to Re: Efficient Looping Constructs
in thread Efficient Looping Constructs

The most noticeable penalty of using for(;;) as a simple counting loop is that your code is less readable. Instead of using a C-ism that is unnecessary, why not just use while(1)? Or, while you're at it, why not just count in a more readable fashion? Which is more readable?
my $sum = 0; for (my $i = 0; $i <= $num; $i++) { $sum += $i; } ##### my $sum = 0; foreach my $i (0 .. $num) { $sum += $i; }
To me, LOW and HIGH are very clearly stated in the foreach. In the for-loop, there are more characters involved. In addition, those characters are semi-colons. This is the only place in C (or Perl) where the semi-colon does not indicate the end of a thought. It, instead, indicates the end of a sub-thought. You have a rule, then you have an exception to the rule that's used everywhere! I understand why they did it, and I understand the syntactic reasons for it, too. But, I do not think of for-loops as three separate statements within a block construct. All other block constructs are one statement-one thought. Why should for be any different?!?

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Replies are listed 'Best First'.
Re: Re: Re: Efficient Looping Constructs
by danger (Priest) on Oct 02, 2001 at 01:26 UTC
    The most noticeable penalty of using for(;;) as a simple counting loop is that your code is less readable. Instead of using a C-ism that is unnecessary, why not just use while(1)?

    /me wonders, with so very many C-isms that are part and parcel of the Perl language, why is the 'for(;;)' loop continually singled out as some kind of negative reflection on the programmer?

    OK, I guess I just don't buy the readability argument. Less readable for who? I would agree that the foreach version *looks* cleaner --- but the fact is that when I am 'reading' code (as opposed to just looking at it) my brain is in code-mode, and the C-style version is simply *not* any harder for me to read (or write for that matter). And it probably wouldn't be any harder for anyone else who knows the C-style version to read either (and there isn't any point comparing readability between those who know it and those who don't). Your suggestion to use a 'while' loop rather than an equivalent C-style for loop might make it *less* readable (the for loop has the key information all together in one place).

    In complete honesty, I think the difference in readability between the for(;;) and foreach forms of a counting loop is *less* than the readability difference between cuddled and uncuddled else clauses (for those who prefer one style over the other). Even if we personally feel very stongly about cuddling or not cuddling, we simply accept that some people will do it differently and we don't make a big deal about it (at least not in a prescriptive manner).

    I am not trying to be a cultural relativist here --- all ways aren't equally good. Using grep() to test if an element exists in a list is using the wrong tool for the job. But I simply can't see the same objection being applied to 'for(;;)' as a simple counting loop. A more relevant concern may be not whether one uses either version to iterate over a range of numbers, but whether they are iterating over numbers for the wrong reason, ie:

    #1: for (my $i = 0; $i < @array; $i++){ $array[$i] += 10; } #2: foreach my $i ( 0 .. $#array) { $array[$i] += 10; }

    The problem with both of these has nothing to do with style of the counting loop, but the fact that they use a counting loop at all.

    My point was never to argue that 'for(;;)' is better or worse than 'foreach' for counting loops. I was arguing against judging someone else's experience and understanding of Perl based on their choice of one construct. Especially when that argument is based on benchmarks that can be both misleading and are essentially vacuous with regard to the real world performance of an application.

    That being said, sometimes performance is a real factor. As a point of history, and as I've mentioned before, using foreach my $i (1 .. 1000000) may look clean and neat, but it wasn't always a very smart thing to do. Prior to version 5.005 (mid 1998), that loop built the million element list in memory and thus could have very *real* performance consequences (show stopping consequences in fact). Therefore, it is quite easy to imagine that someone could have learned this lesson (say, in 1996) and acquired a preference for the 'for(;;)' loop to iterate over ranges of numbers as part of their *Perl* vocabulary (not just as a leftover "C-ism") due to having *more* (or at least longer) experience with Perl (rather than less, as the original poster assumes).

      I would agree that the foreach version *looks* cleaner --- but the fact is that when I am 'reading' code (as opposed to just looking at it) my brain is in code-mode, and the C-style version is simply *not* any harder for me to read (or write for that matter).

      Isn't *looking* cleaner what we strive for when we attempt to write "clean code"? In fact, if there are two completely identical constructs that

      • do the exact same thing
      • have identical CPU usage
      • have identical RAM usage
      We, as responsible programmers, would choose the one that's easier to read in more instances.

      And it probably wouldn't be any harder for anyone else who knows the C-style version to read either (and there isn't any point comparing readability between those who know it and those who don't).

      I've been writing C for 7 years. I can read the for(;;) construct, but I don't like to.

      • It's cluttered.
      • It's forced.
      • It's an eyesore.
      • It's an exception to how all other statements in C are built. (Only place where semi-colon doesn't terminate a statement.)
      The foreach construct, instead, choose to sacrifice some flexibility for readability. Yes, for some people, there is no appreciable difference in readability. Yet, for others, there is. For your code to be readable to the most people, using foreach is a good choice, where programmatically appropriate.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        Isn't *looking* cleaner what we strive for when we attempt to write "clean code"?

        At this point I think we've spent more brain cycles debating the readability difference of the two forms than may have ever been spent by those reading both forms of loop. But I would like to point out that I made a distinction between *looking* cleaner, and being easier to *read*.

        Consider the case of indentation. Steve McConnel (in 'Code Complete', pp 409-410) refers to a study published in 1983 [1]. In this study, subjects scored 20-30% better on tests of comprehensibility when programs had 2 to 4 spaces of indentation than on programs with no indentation. No big surprise here right? However, it was interesting that while the lowest scores happened on programs with no indentation, the second lowest scores happened on programs with 6-space indentation. The interesting bit is that many subjects reported the 6-space indentation as being easier to use than the smaller indentations, but at the same time had lower comprehensibility scores with 6-space indentation. Thus, for many, the 6-space indentation *looked* better, but in fact it made the code less *readable* or comprehensible.

        I am not aware of any studies comparing readability of the for-loop styles, and I am not suggesting what the results might be one way or the other. I am suggesting that a) what we *think* is more readable may not be the case, and b) I truly suspect that the readability difference (if there is one) is probably very low and would probably fall into the same category as the performace differences found above in this thread (ie: trivial in real life).

        Without a real study, we are left with own viewpoints, and those of other experts who seem to pay attention to these very issues. In my view, the C-style for loop is not harder to read and understand, and I stated it was better than an equivalent while-loop because 'the key information is all together in one place'. You seem to have a very stong dislike for C's for-loop (even in C) to the point of recommending a while-loop instead. Your top three reasons against it come off as fairly subjective (cluttered, forced, eyesore). Your single non-subjective reason is that it breaks the semi-colon terminates a statement rule. I'm just guessing, but the tone of your responses suggest you wouldn't really like the for-loop much better if it used a different separator character.

        The opinion of other experts seems to be against you in this respect. Steve McConnel (same book, p331) says that because the for-loop packages loop control code all in one place it makes for more *readable* loops, and makes *correct modification* easier [2]. Granted, he is contrasting it to other looping mechanisms and not to Perl's foreach form, but then your dislike of C's for-loop appears to go well beyond mere uses of such a loop in Perl, and thus stongly colors any argument you make about its readability in Perl.

        [1] Miara, Richard J., et al. 1983. "Program Indentation and Comprehensibility." Communications of the ACM 26, no. 11 (November): 861-67 [2] He is talking about simple for-loops, not for-loops with extra non-loop-control-code packed into the header of the for-loop. But we aren't talking about those kinds of for-loop abuses here either.