(A hands-on equivalent of the following is found in Learn to Program: Loops.)


A "for loop" is literally an iteration construct that uses the for keyword. Practically every imperative programming language has it; some examples:


  for (i=0; i<n; ++i) { do_it(i); }            /* C */

  for (my $i=0; $i<$n; ++$i) { &do_it($i); }   # Perl

  for i = 0 to n
    DoIt i
  next i                                       ' Visual Basic

  FOR i FROM 2 TO 10 BY 2 WHILE foo(bar)
  DO
    do it (i);
  OD                                           # Algol 68 #
 
  DO DOIT I = 2, 10, 2                         C FORTRAN

The syntactic pattern of the C construct has been followed by many other languages. The inclusion of the FORTRAN example is explained below.

The exact meaning of the construct varies with the language.

In Algol 68, the loop variable i is implicitly declared, meaning that its value cannot be read or set outside the loop (although a different variable, also named i, may exist there).

Of particular interest is the fact that within the loop, i is treated as a constant: its value cannot be modified. The TO, BY and WHILE parts are all optional; their values are evaluated once when the loop is started.

By contrast, in FORTRAN, C, Perl, Visual Basic, and many other languages, the loop variable is the same as any i outside the loop - although the Perl example changes that by using my - and the variable's value can be freely modified within the loop and outside the loop.

However, it depends on the language whether the loop parameters are evaluated only once, when the loop is entered, or each iteration over, in which case they affect the number of iterations.

Another form of for-loop, similar to the Algol-style one, is found in the Bourne shell: but instead of being an incremented number, the iteration variable takes its values from a given list of words, often obtained through filename globbing or some other list generating construct:


  for i in word1 word2 word3 word4
  do
     doit i
  done

Like in Algol and Pascal, a scope is implicitly created for the variable, and the number of iterations is bounded at the time the loop is entered.


Much more can be said about the details of for loops in various languages, but the above should be enough to get the general idea across: a for loop is typically used to program bounded iteration, a loop for which the maximum number of iterations is already known at the time the loop is started. Some languages even restrict it to allow nothing else.

Meanwhile all these languages have while loops in which the iteration condition can depend on anything that happens in the loop body, including the value of yet unknown data.

This distinction between bounded and unbounded iteration has nothing to do with syntax, but is purely semantical. To a programmer, it is much more relevant than any syntactic detail because it represents a difference in expressive power: some programming problems can be solved by using bounded iteration only while others cannot.

Therefore, a programmer discussing "for loops" may well be referring to bounded iterations. It is for this reason that it makes sense to call the FORTRAN construct above a "for" loop.

Since it has been claimed that 6.001 doesn't use for loops, a generic function that can simulate "for", used in 6.001, called "accumulate", written in Scheme:
(define accumulate
  (lambda (initval argextract nextval termfunc termval function accumulator basecase)
     (let ((arg (argextract initval))
           (nextarg (nextval initval)))
       (if (termfunc termval arg)
         (accumulator (function arg) basecase)
         (accumulator (function arg)
            (accumulate nextarg argextract nextval termval function accumulator basecase))))))

(define (for a b func)
   (accumulate a (lambda (x) x) inc = b func (lambda (x y) #t) #t))

Note that this would have been more clean with a helper function.
The for loop is one of the most common loop structures available in procedural and procedural based object oriented languages. Unfortunately, at some point in the history of these languages, some differences in syntax and style have occurred.

In each language group, two snippets will be presented (please note that the exact code may not be correct, however, the for loop will be). The first will be count from '1' to '10'. The second will be count from '100' to '10' - counted by 10s.

The earliest instance of the for loop comes Algol. The following example is from Algol 60

for i := 1 until 10
do
  print i
od

for j := 100 step -10 until 10
do
  print i
od
This barely shows the power of the for loop and the flexibility it has. Unlike most languages to follow, ALGOL 60 did not need the step to be an integer. '1 step 3.14159 until 100' was perfectly valid. Furthermore, the range is very flexible as a list of expressions:
for index := 1 step 2 until 50, 60, 70, 80, index +1 until 100 do
results in index = (1, 3, 5, 7, ... , 49, 60, 70, 80, 81, 82, ... , 100). Other oddities of the Algol loop include that the parameter list is re-evaluated every loop. This can cause some hedaches (as seen in the above example).

The iterative loop that is associated with 'for' within FORTRAN is the do loop. This loop provides the same functionality as the for loop.

The do statement has the following format:

DO n I = INITIAL, LIMIT, STEP
The loop index may not be changed within the loop, and modification of variables in the constraints will have no effect upon the loop itself if done within the loop.
   DO 20 i = 1, 10
    PRINT*, i 
20 CONTINUE

   DO 40 j = 100, 10, -10
     PRINT*, j
40 CONTINUE
It should be noted that the classic use of indexes starting with 'i' comes from FORTRAN. Within FORTRAN, an integer value must begin with one of: i, j, k, l, m, n. Real values may start with any other letter. Thus 'i' was the first integer variable for use, 'j' the next and so forth. 'index' was also always an integer variable within FORTRAN, but 'control' was a real variable.

Pascal and various forms of basic use this style of for also though not quite as flexible as Algol's for. Within Pascal:

for i := 1 to 10 do
begin
  writeln(i);
end;

for j := 100 downto 10 do
begin
  if(j % 10 = 0)
  begin
    writeln(j);
  end
end;
You will note the lack of the step used in the downto. In various dialetcs of the pascal language (unfortunately, it is not well defined) the step option to a for loop is not available. An alternate way would be to count from 10 to 1, and multiply the value by 10 before printing it. Furthermore, there is no way to leave a loop in pascal other than with goto.

The code in BASIC languages is similar to that of pascal:

for i = 1 to 10
  print i
next i

for j = 100 to 10 step 10
  print i
next i

As a surprise to some, there was no for loop within the B programing language. The C syntax for loop that is found in C, C++, java, perl, Tcl, and several other languages has 3 parts to it

  • Initial values
  • test (while true, the loop continues)
  • increment
This explicit definition is from the historical close relationship between C and assembly, allowing for a simpler complier and more explicit control over exactly what is happening. Furthermore, other design choices:
  • There is no explicit loop variable
  • Everything can be changed in the loop
  • Pretest
  • The first expression is evaluated once, but the other two are evaluated with each iteration
  • This loop statement is the most flexible
(from http://courses.cs.vt.edu/~cs3304/Fall01/notes/)
for (i = 1; i <= 10; i++)
  { printf("%d\n",i); }

for (j = 100; j > 9; j -= 10)
  { printf("%d\n",j); }
Any of these parts may be empty, allowing for an infinite loop if the test is empty. It is not uncommon to see for (;;) in C code. Furthermore, there is nothing saying that any of these parts have to have anything in common with any other part. for (line = 1; !feof(file); line++, total++) which runs until the end of a file. Multiple statements may be done within a single expression (in this case, the value would be the last one done, not that it matters here).

C++ and java have the added ability of being able to declare the variable that has the scope of the loop within the initial setup.

Scripting languages often have the array of indexes defined rather than as an expression. In csh one finds 'for file (*.gif)'. Python and perl both allow for similar structures:

Python                 | Perl
for i in range(10):    | for $i (1..10)
  print i+1            |   { print $i; }
                       |
(The range(n) function produces numbers from 0 to n - 1. Hence, it is necessary to add 1)

This style of for loop is more often thought of as a 'foreach' loop (in perl, for may be used as a C style loop, or an alias for foreach which also exists). Unfortunately, it is not quite as flexible as the for loop because the array needs to be built with all of the indexes. This also means that when a large number of indexes is required (integrating from 1 to 1,000,000), the entire list of 1,000,000 elements must be built. This can be wasteful of memory. Python does have an xrange function that only returns one element at a time, avoiding this problem.

Python:
for j in [100,90,80,70,60,50,40,30,20,10]:
  print j

Perl:
for $j (map { $_ * 10} (10 .. 1))
  { print $j; }
This style of loop does have the advantage that it dosn't matter what you stick in it - the foreach style loop can work on anything, be it numbers or words. The order it runs in is the order that the array contains.

Python's for loop also allows the use of multiple indexes at the same time.

for i,j in ['a',1,'b',2,'c',3]:
  print '%i - %s' % (i,j)
produces the following output:
a - 1
b - 2
c - 3
The iterator will assign values in order to each variable from the list that is provided. Combining this with the zip function that returns an interwoven list from two or more lists (if they are unequal size, it stops with the shortest one) this can be very useful. The iterator can work over any sequence or object (the list iterator used above simply returns the next element in the list, however, iterators are not confined only to lists but can be used with any object where a next function can be created).

Please do realize, that in almost every language, the for loop is one of the most flexible loops providing for a large range of possible code solutions that is impossible to do more than hint at. This has been a survey of the for loop and was by no means meant to be an in depth study of the for in various languages.

There are two really different things which go by the name of for in different programming languages: the counter for loop (e.g. in Pascal), and the general for loop (e.g. in C). There's also the foreach thing (as in csh), but we'll get to that later. To compare these, I'll try and explain why we have for. So, first off, what is the for loop for? Then, we'll see the two "for"s. And for dessert, we'll talk about encapsulating complex fors in iterators (as in Python or C++/STL). I'm starting with some "philosophy of programming languages" musings, but hopefully this will help explain why superficially similar things called for are different, and it will lead into some discussion of actual languages' for commands.


What is the for loop for?

A loop is a bit of code which we'll be executing over and over. It's the generic and ubiquitous concretisation of the concept of iteration. Almost always, we want to keep looping until some condition occurs. Many languages provide this simple capability through a while loop (or do-while], and/or through a repeat until loop -- the difference between the two is whether you first perform the loop body (repeat), or first check for the exit condition (while). You might continually read input from the user, until she enters a specified delimiter, or iterate a numerical algorithm until your error bound is sufficiently small. You could do this with an if and a goto or jump (if your language is yucky enough to have those), but that doesn't emphasise the loop condition. The while (condition) loop underlines this important bit of your code's structure. (In fact, since goto is almost always used for this purpose, or where a separate function is called for, it is quite uncalled-for in any high-level programming language.)

However, one very common type of loop performs the exact same operation for different values of one particular variable. The loop might have to increment all the values in an array, or calculate a function for a list of inputs, or just perform something a given number of times. For these examples, the important variable might contain (for each iteration) a pointer or index into the array, an index to or the actual value of the current input, or the number of the iteration we're on. In many cases the loop variable is actually a loop index (and is often called this, even when it isn't an index to anything). This is probably why the leading generic loop variable name is i.

Call it what you will, the loop variable is (conceptually) special in that the loop code always does "the same thing", in some sense, and then "advances" the loop index to the next value. You can do this with a while loop, but that doesn't emphasise the loop index. If the last line in your while block "just happens' to increment an index (or follow a pointer, or however you move to the next value) it doesn't stand out as much as when the syntax makes it occupy a different place. So, given it doesn't provide you with much extra functionality (or even save much typing), this syntactic encapsulation is really what for is for.

This matter of having syntax emphasise program structure is important several different ways. It makes code more readable (which is not to be sneezed at), and develops common idioms. But it can also help compilers (maybe even interpreters) optimise the resulting machine code, by saying more about what's going to happen when the entire block is executed. This is most important by far where (for) loops are concerned, as the heaviest part (computationally) of almost any program or function is one or several particular loops, and computer architecture is designed with their optimisation in mind. But that's a whole other matter.


Counter for loop, general for loop

If you examine the examples above of loops and their indices, you'll notice they can all probably be implemented using a counter: an integer index, counting from 0 (or 1, in some languages) up to some given length or number. In a way, this is always true, but in some cases you'll be losing the syntactic encapsulation praised just now. If you're just counting your iterations, or performing an operation on values of i from 0 to 99, your encapsulation is perfect. If you actually have an array nums, and you never use i itself, but only access the ith value, numsi, then syntactically you're not saying all you could about your special (loop) variable, but an intelligent reader (and and intelligently written compiler) can probably figure it out. But what if you're going through all the permutations of a given size, and the way you determine the next permutation has nothing to do with the number of iteration you're on? You could do this with a (formal) loop index which is just a counter, but then you've obviously got some other "real" loop index hidden away inside the for block, so again it doesn't emphasise the loop index. You'd probably be holding a permutation in some other variable, with some bit of code responsible for generating the next value. This basically means you've gone back to the while loop structure, and the syntax hasn't been any help to you.

This brings us to the great divide between different languages' for loops. Pascal and its ilk (Fortran, Algol, Basic and others) concentrate on the counter loop cases: an explicitly named variable is assigned successive values in a given arithmetic sequence, usually on the lines of for i := 3 to 17 step 2, and may not be assigned to (changed) within the for block. Whether or not the parameters may be floats (non-integers), and how the for statement is constructed is of minor importance. This abstracts precisely the idea of a loop with a simple counter index, making things very clear to people or compilers reading the code. It's not very general, though.

C-style for abstracts some other properties of for loops, namely that they have some initialisation before the first step, some "while" condition, and some simple way of proceeding to the next step. If it is a counter loop, it will just come out as for (i = 3; i < 17; i += 2), but no variable is assigned special significance or properties; all three parts of the statement could refer to different variables, or whatever. For the permutation example above, the for statement might be for (p = IdPerm; p != LastPerm; p = next_perm(p)) (assuming you had all the types and constants defined, and next_perm the function to choose the next permutation). This flavour of for is certainly very flexible. The values of the loop variable can be strings or integers or some user-defined type, they advance by whatever method is chosen, and there needn't even be one specific for variable. Yet the information on the basic framework of iteration is right there in the three-part for. Possibly, though, it's marginally easier to compile optimised code for a counter-style loop in Fortran than it is in C, because more restrictive syntax means more knowledge of what's about to happen (e.g. to the loop variable). I doubt anyone takes this very seriously nowadays.


foreach

Many shells (e.g. csh) and some real languages (e.g. Perl) offer a foreach command. This is not like a for command at all, since there is no rule specified to advance from one loop variable value to the next. Instead, an entire list or array of values is given, and the loop variable is assigned each of them in turn. This is sometimes a useful shortcut when you're crunching text (and anyway you get your values as lists from globbing or greping or other manipulations), but for long or hard-to-generate lists it's no good at all.


Encapsulating complex iterations -- OO iterators

Flexible as it is, the C-style for sort of assumes all three parts of the for statement are very brief. What if the loop "step" isn't ++i (increment i), but instead requires several lines of code? You could encapsulate that functionality in a function (as in the next_perm example), but then with complex data you might end up with an initialisation function, a condition function, and a step function; as usual, you lose the emphasis. Object oriented programming philosophy would deem this wasteful clutter.

C++ and the Standard Template Library that accompanies it use the C-style for, but define iterator objects which follow a given protocol; in particular, iterators have a ++ operator and a dereferencing operator, so you can do for ( p = start; p != end; p++ ), where p is of your very own class T, using whatever's defined in operator++ to advance. All of this will work for any iterator, so as long as p is declared of templated class T, the same for loop will handle all different iterators.

Python recently took this a step forward (mostly by exposing some internals). Iterators in Python are not just some things you can use in a for loop; they are the only objects acceptable. Python gives up the three-part for, but doesn't turn it in for a counter loop. Instead, the syntax is just

for i in values:
  ... whatever ...

Where values is any iterable object (basically, an object from which you can obtain an iterator whenever you like). The whole chore of encapsulating the iteration framework is removed from the for loop: the type or class of values is responsible for that. The loop variable is named explicitly (though Python itself makes no special use of this). A list, for example, is an iterable object; it iterates the way you'd expect, by returning the next item in the list every time. Other classes may return any values: aside from a small technicality, the only requirement of an iterator is that it must support the next() method; the for command above simply does (internally) i = values.next() whenever it loops round. Whenever the iterator is done (having checked whatever condition is dear to its heart), it raises an exception, which the for catches, causing it to exit the loop.

values could be just a list, given explicitly or generated by something like range(100) to do i=0, i=1, ..., i=99. For a true counter loop (without the wasteful pre-generated list), Python provides the xrange iterator; xrange(100) will supply the values 0, 1, ..., 99, but without ever generating the entire list. Other iterable objects, of built-in or user-defined classes, provide the for loop with the classical three parts of the for loop, but bundle them away together so the detailed workings don't have to be written out again and again. The loop over permutations which we've been considering might be written as for p in perm_range(perm1, perm2):. Note that here the perm_range object is a single object which can be passed around, and used by any function which uses the iterator protocol, whether or not it was designed with perm_range in mind. For instance, Python converts any iterable object into a list by looping over its iterator, and appending each value to the previous ones.

Incidentally, once you have iterators, it's easy to write operators to combine them into more complex iterators, or to transform them in various ways. Python offers the latter in map, filter, and list comprehension.

In the curly brace family of programming languages, ie C and derived languages, c-style for loops are Ubiquitous. For loops in these languages are the swiss army chainsaw of looping. They'll do anything if you set it up right.

For loops in Pascal are less flexible than this in some ways and more flexible in others. Pascal style for loops are only for for repeating yourself a fixed number of times.

In the following, I will be showing code for Delphi, the most common pascal variant in use from the late 1990s. Your millage may vary in other pascals.

Pascal for loops always increment or decrement an index variable, whcih must be pre-declared like all others. The most restrictive scope to which you can declare this variable is the enclosing procedure or function.

var
  iLoop: integer;
begin
  for iLoop := 1 to 100 do
  begin
   // this happens 100 times
  end;

  for iLoop := 100 downto 1 do
  begin
   // this happens 100 times, reverse order
  end;

Unlike a while or repeat loop, the bounds are evaluated once only – they are not tested at the end of each iteration. So if you code
var
  iLoop: integer;
begin
  for liLoop := GetMin() to GetMax() do
 begin
   // changes here to the result of GetMin() and GetMax() have no effect on the looping
 end;
end;

Flow of control with the loop can be changed with the break statement, which exits the loop, or the continue statement, which ends the current iteration and continues with the next one. Note that neither of these are in the original pascal specification. However life without them would be annoying.

Pascal’s most fun for-loop feature is that the loop index need not be an integer, it can be any ordinal type. You can loop over char, an enum or over boolean (with a grand total of two possible values). Here's an example for looping over an enum:
type
  TCardSuit = (csHearts, csClubs, csDiamonds, csSpades);

var
  SuitLoop: TcardSuit;
begin
  for suitLoop := Low(TCardSuit) to High(TcardSuit) do
  begin
   // do something with the suit ...
  end;
end;

In recent times the foreach loop in languages such as PHP and C# has taken over some of the simpler tasks of for loops, by iterating over all elements in a list or collection with even less effort.

Log in or register to write something here or to contact authors.