It seems there is a modern-day vendetta in the programming community against the humble loop. It started with iterators, and then the C++ template library, where collections were traversed by a function and you had to plug in your little callback for the processing done with each item. LINQ came along and furthered the nefarious ends of SQL to eliminate iteration in all its forms except those implemented by the query engine. And finally, functional programming has come along and reduced all looping to recursion with lambda functions.
And what has the poor for-loop (or while-loop or do-loop, etc.) done to deserve such treatment?
Seriously. That’s not a rhetorical question.
I played along in the early days. But then I noticed that there were two conditions that kept recurring and forced me to write the for-loop myself. The first condition was when I needed to know the index of the current item (or in the case of searches, of the item found). Trivial to know with a for-loop iterating over an index; with iterators you needed an extra counter variable. Functional programming would deny the need to ever use an indexer. Cute.
The second condition was early exit. Often when looping — whether searching for something or doing some kind of accumulated calculation — you want to exit when a certain condition is hit. Again, trivial if you are writing the for-loop yourself; difficult if you abrogate the loop to some other agent’s control.
And what have we gained by avoiding the for-loop? We’ve saved a line of boilerplate code:
for (i = 0; i < list.Length; i++)
Ok. That is a small savings in effort. But does it justify the huge loss of control? It’s easy to read, easy to understand, easy to debug — there is nothing hidden in it. And it is under your full control. And I find that with the other looping constructs that I miss the syntactic marker that says “this code is dealing with many items and might not scale!”
Now I wouldn’t be so foolish as to suggest that iterators, callbacks, lambdas, and LINQ don’t all have their places. Certainly there are circumstances where the value of the expressiveness of these other constructs is truly compelling. But that is a far cry from implying that loops are to be avoided at all costs as often seems to be the case in the blogosphere and the ridiculous world of “best practices”.
What I’m arguing for is clarity. I’m not arguing against expressiveness or conciseness, but I most definitely prioritize clarity over them. So when trying to figure out how to code a collection operation of any type, don’t forget the humble loop.