in reply to Re: 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)?

/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).

Replies are listed 'Best First'.
Re4: Efficient Looping Constructs
by dragonchild (Archbishop) on Oct 02, 2001 at 19:42 UTC
    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.
        After thinking about this for a while, I realized the biggest Perl reason why foreach, in my mind, is more readable than for. It's the fact that so much in Perl is predicated on lists. map, grep, push, etc ... there's so much about lists. Then, all of a sudden, I go from dealing with a list to dealing with the implementation of a list. I don't care about index numbers - I care about the holistic, organic list. :-)

        To reply to your node, I have read Code Complete and do remember both sections you refer to.

        The indentation study ... it was interesting, but he was using it, in my opinion, more to discuss that indentation systems aren't arbitrary vs. readability issues.

        As for the looping mechanisms ... for-loops do package a lot in a single place. That's their benefit and their Achilles' heel. Yes, I do have a beef against for-loops, primarily because they've been abused way too much in C. I remember reading some for-loops where the conditions had more lines than the block itself!

        I do use for-loops when they make sense in Perl. I prefer the foreach construct (but will use the word 'for' instead of 'foreach'), primarily because it says only what it needs to say. I'm a fan of minimalist programming - say only what you need to say and no more. for-loops tend to say more than what's needed.

        ------
        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.