Are there any cases when For[] loops are reasonable?

To my mind, there are at least two cases when For loops are ok:

  • Inside Compile, or in code which is being written with Compile in mind
  • When your inner loops are vectorized or made efficient by some other means, so that each iteration of the For loop is sufficiently intensive computationally

Many efficient algorithms are procedural by nature and gain their efficiency by side effects and local mutations. When those algorithms contain nested loops, what matters the most is to speed up innermost loop(s). While we mostly tend to move away from For loops, I have no problem with a For loop being an outer loop in a program, as long as innermost loops are optimized. Also, For loops are more flexible than Map or Scan because you can use Break and Continue, and generally are not forced to iterate over all of the elements in a list in a prescribed order.

That said, I think we should recommend beginners to avoid For loops, just because this would allow them to change their mindset and get to the better understanding of Mathematica programming sooner. I'd say, it is ok to occasionally use For loops for experienced users, but beginners would be better off avoiding them entirely, until they get more experience with the language.


Choosing Adequate Loop-Constructs

While there are many loop-like constructs I think there are 5 that every Mathematica programmer should know, 4 of them come as pairs which either do return the result of each iteration or don't, but otherwise share syntax:

  1. Map - Scan
  2. Table - Do
  3. While

As a general rule it is a good idea to always use the most simple construct that provides the functionality you need: A large majority of loop constructs do iterate over a given list/array and Map or Scan would be the best choice for these. They do away with any kind of indexing and iteration issues. In some cases it is useful/necessary to have a handle to a loop counter, this is what Table or Do provide. If you need a more flexible iteration scheme, then there is While, which is providing the most general case of a loop that I can think of. Using "more advanced" loop-like constructs in my opinion is only worth considering when they exactly match your use case and make that basically a one-liner. If you need tricks to map them to your use case that will often result in rather "write only" type of code. I would rather urge users to have a look at level specifications for Map/Scan and additional arguments for Table/Do (to specify nesting loops and step sizes) and the Sow/Reap mechanism to collect results from a arbitrary loop.

Why Not to Use For-Loops

While many of these other loop-like constructs in Mathematica have their use cases, I would strongly discourage the use of For loops: I have never used one in any Mathematica code I ever wrote. As mentioned by Leonid in one of the comments in most cases (I'd guess about 95% of the time when I see one) it is Do that is really needed. In the other maybe 5% it is While that is needed. The cases where one might think a For loop would be necessary can basically be reduced to two cases:

  1. You need a loop counter: you'd better use Do or Table, their syntax is more concise, it is much easier to see what they actually do and they localize loop counters.
  2. You need a more complex iteration scheme than what Do or Table provide: I prefer to use While for these cases since it is a lot easier to read and For doesn't add anything but unnecessary complexity.

I consequently use Do/Table for case 1 and While for case 2 (and only for case 2) so when I see Do or While in my code I readily get some extra information about the nature of the loop.

Readability of Code

A While loop is much easier to read than a For loop: There are basically three parts of code within such a loop: initialization, condition-check and body. In a While loop everything that happens before the While is initialization, the first argument of the While is the condition-check and the second is the body. In a For loop you can distribute the initialization between code before the For loop and the first argument, and you can arbitrarily distribute the body part between the 3rd and 4th argument. Consequently it will always need extra thinking about what will be evaluated in which order (see Can this be written well, without loops? for an example: can you see the order of evaluation at first glance? I only realized that the loop counters were incremented after the nested loops after rewriting with While).

Technical Details and Performance

Concerning all the technical details I think For doesn't provide anything that Do and While don't: they return Null, they can be compiled (I would guess that both Do and While should even outperform For in compiled code), and you can use Break and Continue within them.

It is not only friendly to a possible reader to use the most simple construct that covers your need. It is just as well easier for Mathematica to understand your code, which lets it do a better job when optimizing the code (of course that holds just as well for other constructs than loops). Auto-compilation of Table is one case, here is another example:

res1 = Table[Table[i*j, {i, 100}], {j, 100}];
res2 = Table[i*j, {i, 100}, {j, 100}];

looks like not much difference and it's easy to check that these in fact create the same result, except for a small detail:

Developer`PackedArrayQ[res1]
Developer`PackedArrayQ[res2]

(* ==> False *)

(* ==> True *)

this can result in tremendous differences in the runtime and memory efficiency of this construct and all the following code which works with the result.

EDIT

There is one more important difference between a typical For loop and its Do correspondance which becomes clear when using floating point counters, compare e.g.:

h = 10.^-5;
Do[If[i >= 1 - h, Print[InputForm@i]], {i, 0, 1, h}]

to:

h = 10.^-5;
For[i = 0, i <= 1, i += h, If[i >= 1 - h, Print[InputForm@i]]]

Of course it really depends on what you want to achieve, but I think in most use cases you would actually prefer the equidistant division that Do seems to do over the accumulated errors of For which make it on my 64bit Mathematica 9 on Windows 7 "miss" the upper limit. It is again an example where Mathematica can act smarter when the construct you use is the simplest possible and thus more clear. If accumulating the errors would be what you actually want to happen, then again a While would still do the same thing with less ambiguities (again it took me a second try to realize that the increment in For is done after evaluating the body, something that is immediately clear in the While code and could accordingly be changed if so desired):

h = 10.^-5;
i = 0;
While[i <= 1, If[i >= 1 - h, Print[InputForm@i]]; i += h;]

I'd argue that For should be used when you want to iterate through a list of options and insure that they are not run in parallel.

To give a silly example, Table[CelebrateBirthday[i],{i,0,18}] is equivalent to For[i=0,i<19,i++,CelebrateBirthday[i]]

However, a later programmer might try and performance tune by changing the first example into a ParallelTable, causing the birthdays to be celebrated in a non-deterministic order. The For loop, on the other hand, signals to any future coders that the loop wasn't designed to be run in parallel and that care should be taken before changing the order of operations.

I'd tell a newbie that, if you want your code to run slowly, use For. Otherwise, use Table or Map.