Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

To my mind the only reason for the existence of For[] loops in Mathematica is to allow new users with some experience in procedural programming languages to write simple Mathematica programs. The real problem is that sometimes such a user do not dive deeper and as a consequence he has 1) ugly and unreliable code and 2) a belief that "Mathematica has a C-like syntax".

It is hard for me to imagine a situation when For[] can not be effectively and more cleanly replaced by Table, Map, anything else or Do at least. Am I wrong? Should we really recommend beginners to avoid For[] loops?


SUMMARY

There are actually two great answers. The first answer is the accepted one and the second answer is this question. I wish I could accept it as well.

share|improve this question
    
No reason for them except simply because people want to use them. They're slow. Mathematica has labels and Goto statements as well. I don't recommend them. –  Searke Feb 22 '12 at 18:45
2  
@Searke I've had one occasion where I used Label and Goto: figuring out what a FORTRAN code was doing. –  rcollyer Feb 22 '12 at 18:54
    
Oops, I didn't know For was bad...! The advantage, as I thought, over functional structures, was that you didn't accumulate temporary results like you do with Table. For example, in each iteration, I'd create a graphic, and write it to disk. If I used Table to collect images, Mathematica crashes after 10 minutes... I promise to read about Do tomorrow... :) –  cormullion Feb 22 '12 at 20:10
1  
@cormullion Have a look at Scan as well. It is as close as one gets to loops from a functional side, but more rigid (iteration order is prescribed, and there are no iteration variables). –  Leonid Shifrin Feb 22 '12 at 20:14
    
Perhaps if the algorithm you're implementing lends itself very well to loops your code will be most readable if you use loops. –  Andrew MacFie Feb 29 '12 at 23:52

5 Answers 5

up vote 21 down vote accepted

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.

share|improve this answer
4  
I am not sure I see where For loops are preferable to Do, which localizes the iterator (unless you are using For in a more complicated way than For[i = 0, i < 4, i++, Print[i]], but that is probably rare) –  acl Feb 22 '12 at 18:58
4  
@acl I agree, that in many cases where For is used, Do is what you really need. Some cases when you may want For (or While, which is its close relative), is when you either need more complex iteration, ot the number of iterations may not be known in advance (like e.g. in this code), or when you want to use Return to return from the entire function containing a loop (using Return from Do will only break from Do). –  Leonid Shifrin Feb 22 '12 at 19:03
1  
@Eli Lansey In uncompiled code, Do is typically more efficient that While, and Map can be much more efficient still, since it can auto-compile when the function being mapped is compilable. Note that Map is also different in that it procuduces the resulting list, while Do or While (or For) return Null. In compiled code, Do is still the fastest, and in my experience While comes second, and Map is somewhat slower IIRC. –  Leonid Shifrin Feb 22 '12 at 19:48
1  
@Artes ..flies in the face of extreme generality of the term-rewriting engine of Mathematica. A better strategy IMO would be to introduce more strongly typed sub-languages within Mathematica, so that programs written in those sub-languages could be compiled. This is the direction which I think has a great potential. In a sense, Compile defines one such sub-language, but I am sure it should be possible to define other sub-languages, and write custom compilers from those to C or whatever target language you want. Integrating those with efficient Mathematica low-level structures is hard though. –  Leonid Shifrin Feb 23 '12 at 13:26
1  
@JacobAkkerboom Thanks. I'd actually like to do some work in this area of creating tools for such workflows. It is hard to find time for that though, these days. Remains one of my pipe dreams ) –  Leonid Shifrin May 18 at 13:07

Choosing Adequat 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[res2]
Developer`PackedArrayQ[res1]

(* ==> True *)

(* ==> False *)

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;]
share|improve this answer
    
+1. I actually consider For and While to be very close to each other, because both are inherited from C (in terms of syntax), where the difference between them is more a matter of personal preference (you can leave out some parts of for and have while, like for(;condition;){}). So when I was speaking of For loops, I meant both For and While (I should have stated that in my answer), and admittedly I also often prefer While to For. –  Leonid Shifrin Feb 23 '12 at 11:49
    
@Leonid: you are of course right, and it might be worth mentioning that one can leave out parts in a Mathematica For as well (use Null if you don't want to see the syntax highlight warnings). But that is my criticism: For seems to add complexity without actually provide new features compared to While. Thus my preference for While: it doesn't add unnecessary load to my brain :-) –  Albert Retey Feb 23 '12 at 13:09
    
Yes, I agree. All your points are very valid. I think our answers are complementary to each other. –  Leonid Shifrin Feb 23 '12 at 13:17
    
@AlbertRetey, hehe, here I could sneak in another +1 ;-) –  user21 May 8 '12 at 17:36
    
A little remark: readability of code is rather subjective. –  TZakrevskiy Mar 30 at 11:46

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.

share|improve this answer
1  
also, Table attempts to autocompile –  acl Feb 22 '12 at 19:49
1  
Those would be equivalent if Table was Do –  Rojo Feb 22 '12 at 22:46
3  
If you want a reader of your code to know that a loop is not to be parallelized I think a comment would server much better than the use of a suboptimal programming construct which, in principle, could be target of parallelization just as others... –  Albert Retey Feb 23 '12 at 11:06
    
@Albert I agree that a comment would be the better options, but a belt and suspenders approach would argue that it makes sense to do both. Also, while a programmer can sit down and try and turn a For loop into parallel code, already has a built in ParallelTable, ParallelMap, and ParallelDo, but no ParallelFor. If a future programmer wants to parallelize the For loop, she's at least going to be forced to read the code first. –  user640078 Feb 23 '12 at 17:24

I have used a For (or more usually While) loop in conjunction with Sow and Reap when I am unsure of the number of iterations I will be requiring. I'll iterate until a condition is met, and Reap all the solutions.

Note: There might be a better/faster way that I'm unaware of to do this same sort of thing.

share|improve this answer
    
I use For in the same circumstances, provided I don't know how many iterations I'm going to need and I also need an iteration counter. In some cases, it may be possible to work out the number of iterations outside the loop, in which case Table[] becomes useful, but if that determination is sufficiently complex and introduces the possibility of (programmer) error, Table[] may be an easier and potentially more robust solution. –  Michael Stern Feb 29 '12 at 14:43

Nobody mentioned use of Throw, Catch for very versatile exiting from loops.

share|improve this answer
2  
I actually would not recommend this technique for standard situations. If you have nested loops, you can wrap Module around them end exit with Return[..., Module], or just Return. Exceptions are for exceptional circumstances IMO. Besides, people tend to abuse untagged exceptions, which are pretty bad (I consider Throw and Catch without tags a language defect), so this would just lead to lots of trouble IMO. Finally, exceptions cause an overhead, and I'd expect that they can not be compiled and will slow down the code if we use it (code) inside Compile (although I did not try it). –  Leonid Shifrin Feb 22 '12 at 20:19
    
In my RootSearch package I call an iterative algorithm which looks for a root where there is likely to be a root. That algorithm calls a function which calls a function and so on. A few functions deep it may be discovered that the function whose roots we a looking fo is not defined at the new approximation of the root. When that happens I use Throw to give up on the iterative algorithm in that neighborhood. I don't know if you call that an exception. Also, we can use Check to take certain action when we compute 0/0 etc. –  Ted Ersek Feb 22 '12 at 22:06
    
This sounds like a more involved flow of control than simply nested loops, in which case exceptions (Throw) may be justified. I expressed my views on this in this answer, albeit in the context of error-checking. One thing I am absolutely opposed to is using Throw as Throw[expr] rather than Throw[expr,tag]. I think it is totally acceptable to use Throw-Catch to implement non-trivial flow of control, but this should be reserved for cases when nothing else helps. –  Leonid Shifrin Feb 22 '12 at 22:26
    
Also, while it is hard for me to make conclusions without looking at the code, but normally, even for involved algorithms, I almost never saw a situation when the logic could not be implemented with local gotos (Break, Continue, etc) and really cried for Throw-Catch. I still think that these belong more to the software engineering side of the language than algorithmic, and should be used as such most of the time. This is just my opinion, of course, you don't have to agree with it. –  Leonid Shifrin Feb 22 '12 at 22:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.