Hubbry Logo
For loopFor loopMain
Open search
For loop
Community hub
For loop
logo
8 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
For loop
For loop
from Wikipedia
Flow diagram of a for loop that prints five asterisks.

In computer programming, a for loop is a structured control flow statement that repeatedly runs a section of code until a condition is satisfied.

A for loop has two parts: a header and a body. The header defines how the loop iterates, and the body is the code executed once per iteration. The header often declares a loop variable which can be used in the body to know which iteration of the loop is being executed. A relatively simple for loop iterates for a fixed number of times. For example, the following C for loop declares a loop variable i and prints its value as it increments from 0, 1, and 2:

for (int i = 0; i < 3; ++i) {
    printf("%d", i);
}

Depending on programming language, various keywords are used to denote a for loop. For example, descendants of ALGOL use for,[1] while descendants of Fortran use do and COBOL uses PERFORM VARYING.

Variations

[edit]
For loop illustration, from i=0 to i=2, resulting in data1=200

Generally, a for loop falls into one of the following categories:

Numeric

[edit]

A numeric for loop increments a control variable from a start value to and end value. In languages such as ALGOL, Simula, BASIC, Pascal, Modula, Oberon, Ada, MATLAB, OCaml, and F# it looks like:

for i = first to last do statement

Some languages support an optional step value (increment or decrement). Some languages require a separate declaration of the control variable.

3 part

[edit]

A 3-part for loop, popularized by C, has the following parts separated by semi-colons: initialization (loop variant), condition, and advancement to the next value. Each part is optional and can be blank. This syntax came from B programming language and was originally invented by Stephen C. Johnson.[2] In the initialization part, any variables needed are declared and assigned values. The condition part checks a condition and exits the loop if false, even if the loop is never executed. If the condition is true, then the loop's block of is executed. The advancement to the next iteration part is performed each time the block is executed.

The following Java code is a C-style numeric loop that prints the numbers from 0 to 99.

for (int i = 0; i < 100; ++i) {
    System.out.printf("%d", i );
}

This form is often used like the numeric for loop, but is more flexible and can be used for other patterns. For example, for (start(); done(); next()) calls functions instead of using a control variable. The pattern of an infinite loop is implemented as for (;;).

Iterator-based

[edit]

A foreach loop enumerates the items of a sequence. It is usually uses an implicit or explicit iterator, in which the loop variable represents each value of the sequence. The following Python code shows a foreach loop. items is either a data collection that supports implicit iteration, or may be an iterator itself.

for item in items:
    do_something(item)

Vectorized

[edit]

Some languages offer a for loop that acts as if processing all iterations in parallel, such as the for all keyword in Fortran 95 which has the interpretation that all right-hand-side expressions are evaluated before any assignments are made, as distinct from the explicit iteration form. For example, in the for statement in the following pseudocode fragment, when calculating the new value for A(i), except for the first (with i = 2) the reference to A(i - 1) will obtain the new value that had been placed there in the previous step. In the for all version, however, each calculation refers only to the original, unaltered A.

for     i := 2 : N - 1 do A(i) := [A(i - 1) + A(i) + A(i + 1)] / 3; next i;
for all i := 2 : N - 1 do A(i) := [A(i - 1) + A(i) + A(i + 1)] / 3;

The difference may be significant.

Some languages (such as PL/I, Fortran 95) also offer array assignment statements, that enable many for loops to be omitted. Thus pseudocode such as A:= 0; would set all elements of array A to zero, no matter its size or dimensionality. The example loop could be rendered as

 A(2 : N - 1) := [A(1 : N - 2) + A(2 : N - 1) + A(3 : N)] / 3;

But whether that would be rendered in the style of the for loop or the for-all-loop or something else may not be clearly described in the compiler manual.

Numeric & while

[edit]

Introduced with ALGOL 68 and followed by PL/I, the compound numeric and while for loop iterates while the control value increments (as a numeric for loop) and while a condition is true. If the condition evaluates to false, then the loop exits before the loop variable reaches the last value. In the following code, i starts at 1 and the loops iterates until either i is N or Done is true.

for i := 1 : N while not Done do Something()

Loop counters

[edit]

In computer programming, a loop counter is a control variable that controls the iterations of a loop (a computer programming language construct). It is so named because most uses of this construct result in the variable taking on a range of integer values in some orderly sequences (for example., starting at 0 and ending at 10 in increments of 1)

Loop counters change with each iteration of a loop, providing a unique value for each iteration. The loop counter is used to decide when the loop should terminate and for the program flow to continue to the next instruction after the loop.

A common identifier naming convention is for the loop counter to use the variable names i, j, and k (and so on if needed), where i would be the most outer loop, j the next inner loop, etc. The reverse order is also used by some programmers. This style is generally agreed to have originated from the early programming of Fortran[citation needed], where these variable names beginning with these letters were implicitly declared as having an integer type, and so were obvious choices for loop counters that were only temporarily required. The practice dates back further to mathematical notation where indices for sums and multiplications are often i, j, etc. A variant convention is the use of duplicated letters for the index, ii, jj, and kk, as this allows easier searching and search-replacing than using a single letter.[3]

Example

[edit]

An example of C code involving nested for loops, where the loop counter variables are i and j:

for (int i = 0; i < 100; i++) {
    for (int j = i; j < 10; j++) {
        someFunction(i, j);
    }
}

Loops in C can also be used to print the reverse of a word. As:

for (int i = 0; i < 6; i++) {
    scanf("%c", &a[i]);
}
for (int i = 4; i >= 0; i--) {
    printf("%c", a[i]);
}

Here, if the input is apple, the output will be elppa.

Additional semantics and constructs

[edit]

Use as infinite loops

[edit]

This C-style for loop is commonly the source of an infinite loop since the fundamental steps of iteration are completely in the control of the programmer. When infinite loops are intended, this type of for loop can be used (with empty expressions), such as:

for (;;) {
    // loop body
}

This style is used instead of infinite while (true) loops to avoid a type conversion warning in some C/C++ compilers.[4] Some programmers prefer the more succinct for (;;) form over the semantically equivalent but more verbose while (true) form.

Early exit and continuation

[edit]

Some languages may also provide other supporting statements, which when present can alter how the for loop iteration proceeds. Common among these are the break and continue statements found in C and its derivatives. The break statement causes the innermost loop to be terminated immediately when executed. The continue statement will move at once to the next iteration without further progress through the loop body for the current iteration. A for statement also terminates when a break, goto, or return statement within the statement body is executed.[Wells] Other languages may have similar statements or otherwise provide means to alter the for loop progress; for example in Fortran 90:

DO I = 1, N
  statements!Executed for all values of "I", up to a disaster if any.
  IF (no good) CYCLE! Skip this value of "I", and continue with the next.
  Statements!Executed only where goodness prevails.
  IF (disaster) EXIT! Abandon the loop.
  Statements!While good and, no disaster.
END DO! Should align with the "DO".

Some languages offer further facilities such as naming the various loop constructs so that with multiple nested loops there is no doubt as to which loop is involved. Fortran 90, for example:

X1:DO I = 1, N
     statements
  X2:DO J = 1, M
       statements
       IF (trouble) CYCLE X1
       statements
     END DO X2
     statements
   END DO X1

Thus, when "trouble" is detected in the inner loop, the CYCLE X1 (not X2) means that the skip will be to the next iteration for I, not J. The compiler will also be checking that each END DO has the appropriate label for its position: this is not just a documentation aid. The programmer must still code the problem correctly, but some possible blunders will be blocked.

Loop variable scope and semantics

[edit]

Different languages specify different rules for what value the loop variable will hold on termination of its loop, and indeed some hold that it "becomes undefined". This permits a compiler to generate code that leaves any value in the loop variable, or perhaps even leaves it unchanged because the loop value was held in a register and never stored in memory. Actual behavior may even vary according to the compiler's optimization settings, as with the Honeywell Fortran66 compiler.

In some languages (not C or C++) the loop variable is immutable within the scope of the loop body, with any attempt to modify its value being regarded as a semantic error. Such modifications are sometimes a consequence of a programmer error, which can be very difficult to identify once made. However, only overt changes are likely to be detected by the compiler. Situations, where the address of the loop variable is passed as an argument to a subroutine, make it very difficult to check because the routine's behavior is in general unknowable to the compiler unless the language supports procedure signatures and argument intents. Some examples in the style of pre-Fortran-90:

DO I = 1, N
  I = 7 !Overt adjustment of the loop variable. Compiler should complain
  Z = ADJUST(I) !Function "ADJUST" might alter "I", to uncertain effect.
  PRINT *, (A(I), B(I), I = 1, N, 2) !Implicit for loop to print odd elements of arrays A and B, reusing "I"... Compiler should complain.
  PRINT *, I                         ! What value will be presented?
END DO! How many times will the loop be executed?

A common approach is to calculate the iteration count at the start of a loop (with careful attention to overflow as in for i:= 0: 65535 do ... ; in sixteen-bit integer arithmetic) and with each iteration decrement this count while also adjusting the value of I: double counting results. However, adjustments to the value of I within the loop will not change the number of iterations executed.

Still, another possibility is that the code generated may employ an auxiliary variable as the loop variable, possibly held in a machine register, whose value may or may not be copied to I on each iteration. Again, modifications of I would not affect the control of the loop, but now a disjunction is possible: within the loop, references to the value of I might be to the (possibly altered) current value of I or to the auxiliary variable (held safe from improper modification) and confusing results are guaranteed. For instance, within the loop a reference to element I of an array would likely employ the auxiliary variable (especially if it were held in a machine register), but if I is a parameter to some routine (for instance, a print-statement to reveal its value), it would likely be a reference to the proper variable I instead. It is best to avoid such possibilities.

Adjustment of bounds

[edit]

Just as the index variable might be modified within a for loop, so also may its bounds and direction. But to uncertain effect. A compiler may prevent such attempts, they may have no effect, or they might even work properly - though many would declare that to do so would be wrong. Consider a statement such as

for i := first : last : step do
  A(i) := A(i) / A(last);

If the approach to compiling such a loop was to be the evaluation of first, last and step and the calculation of an iteration count via something like (last - first)/step once only at the start, then if those items were simple variables and their values were somehow adjusted during the iterations, this would have no effect on the iteration count even if the element selected for division by A(last) changed.

List of value ranges

[edit]

ALGOL 60, PL/I, and ALGOL 68, allow loops in which the loop variable is iterated over a list of ranges of values instead of a single range. The following PL/I example will execute the loop with six values of i: 1, 7, 12, 13, 14, 15:

do i = 1, 7, 12 to 15;
  /*statements*/
end;

Equivalence with while-loops

[edit]

A for loop is generally equivalent to a while-loop:

factorial := 1
 for counter from 2 to 5
     factorial := factorial * counter
counter:= counter - 1
print counter + "! equals " + factorial

Is equivalent to:

factorial := 1
counter := 1
 while counter < 5
    counter := counter + 1
    factorial := factorial * counter
print counter + "! equals " + factorial

As demonstrated by the output of the variables.

Timeline of the for loop syntax in various programming languages

[edit]

Given an action that must be repeated, for instance, five times, different languages' for loops will be written differently. The syntax for a three-expression for loop is nearly identical in all languages that have it, after accounting for different styles of block termination and so on.

1957: FORTRAN

[edit]

Fortran's equivalent of the for loop is the DO loop, using the keyword do instead of for, The syntax of Fortran's DO loop is:

        DO label counter = first, last, step
          statements
label     statement

The following two examples behave equivalently to the three argument for loop in other languages, initializing the counter variable to 1, incrementing by 1 each iteration of the loop, and stopping at five (inclusive).

        DO 9, ICOUNT = 1, 5, 1
          WRITE (6,8) ICOUNT
    8     FORMAT( I2 )
    9   CONTINUE

As of Fortran 90, block structured END DO was added to the language. With this, the end of loop label became optional:

do icounter = 1, 5
  write(*, '(i2)') icounter
end do

The step part may be omitted if the step is one. Example:

* DO loop example.
       PROGRAM MAIN
         INTEGER SUMSQ
         SUMSQ = 0
         DO 199 I = 1, 9999999
           IF (SUMSQ.GT.1000) GO TO 200
199        SUMSQ = SUMSQ + I**2
200      PRINT 206, SUMSQ
206      FORMAT( I2 )
       END

In Fortran 90, the GO TO may be avoided by using an EXIT statement.

* DO loop example.
       program main
         implicit none

         integer:: sumsq
         integer:: i

         sumsq = 0
         do i = 1, 9999999
           if (sumsq > 1000) exit
           sumsq = sumsq + i**2
         end do
         print *, sumsq

       end program

Alternatively, a DO - WHILE construct could be used:

       program main
         implicit none

         integer:: sumsq
         integer:: i

         sumsq = 0
         i = 0
         do while (sumsq <= 1000)
           i = i+1
           sumsq = sumsq + i**2
         end do
         print *, sumsq

       end program

1958: ALGOL

[edit]

ALGOL 58 introduced the for statement, using the form as Superplan:

 FOR Identifier = Base (Difference) Limit

For example to print 0 to 10 incremented by 1:

FOR x = 0 (1) 10 BEGIN
PRINT (FL) = x END

In ALGOL 60 the looping construct was changed. A series of 'for list elements', separated by commas, can be specified. An element can either be an arithmetic expression element, a 'step-until' element, or a 'while' element.

To print from 0 to 10, then the number 42:

  for x := 0 step 1 until 10, 42 do
    begin
      outinteger (1, x);
      outstring (1, "\n")
    end;

A mostly equivalent loop using a 'while' element could be written:

  x := 0;
  for x := x while x <= 10, 42 do
    begin
      outinteger (1, x);
      outstring (1, "\n");
      x := x + 1
    end;

Note the value of x after the first loop has completed will be 42, whereas in the second loop it will be 43.

1960: COBOL

[edit]

COBOL was formalized in late 1959 and has had many elaborations. It uses the PERFORM verb which has many options. Originally all loops had to be out-of-line with the iterated code occupying a separate paragraph. Ignoring the need for declaring and initializing variables, the COBOL equivalent of a for loop would be.

      PERFORM SQ-ROUTINE VARYING I FROM 1 BY 1 UNTIL I > 1000

      SQ-ROUTINE
             ADD I**2 TO SUM-SQ.

In the 1980s, the addition of in-line loops and structured programming statements such as END-PERFORM resulted in a for loop with a more familiar structure.

      PERFORM VARYING I FROM 1 BY 1 UNTIL I > 1000
             ADD I**2 TO SUM-SQ.
      END-PERFORM

If the PERFORM verb has the optional clause TEST AFTER, the resulting loop is slightly different: the loop body is executed at least once, before any test.

1964: BASIC

[edit]

In BASIC, a loop is sometimes named a for-next loop.

10 REM THIS FOR LOOP PRINTS ODD NUMBERS FROM 1 TO 15
20 FOR I = 1 TO 15 STEP 2
30 PRINT I
40 NEXT I

The end-loop marker specifies the name of the index variable, which must correspond to the name of the index variable at the start of the for loop. Some languages (PL/I, Fortran 95, and later) allow a statement label at the start of a for loop that can be matched by the compiler against the same text on the corresponding end-loop statement. Fortran also allows the EXIT and CYCLE statements to name this text; in a nest of loops, this makes clear which loop is intended. However, in these languages, the labels must be unique, so successive loops involving the same index variable cannot use the same text nor can a label be the same as the name of a variable, such as the index variable for the loop.

1964: PL/I

[edit]

The PL/I DO statement can act as either a for loop, a while loop, or a do until loop.

do counter = 1 to 5 by 1; /* "by 1" is the default if not specified */
  /*statements*/;
  end;

The LEAVE statement may be used to exit the loop. Loops can be labeled, and leave may leave a specific labeled loop in a group of nested loops. Some PL/I dialects include the ITERATE statement to terminate the current loop iteration and begin the next.

1968: ALGOL 68

[edit]

ALGOL 68 has what was considered the universal loop, the full syntax is:

FOR i FROM 1 BY 2 TO 3 WHILE i≠4 DO ~ OD

Further, the single iteration range could be replaced by a list of such ranges. There are several unusual aspects of the construct

  • only the do ~ od portion was compulsory, in which case the loop will iterate indefinitely.
  • thus the clause to 100 do ~ od, will iterate exactly 100 times.
  • The while syntactic element allowed a programmer to break from a for loop early, as in:
INT sum sq := 0;
FOR i
 WHILE
  print(("So far:", i, new line)); # Interposed for tracing purposes. #
  sum sq ≠ 70↑2                    # This is the test for the WHILE   #
DO
  sum sq +:= i↑2
OD

Subsequent extensions to the standard ALGOL 68 allowed the to syntactic element to be replaced with upto and downto to achieve a small optimization. The same compilers also incorporated:

until
for late loop termination.
foreach
for working on arrays in parallel.

1970: Pascal

[edit]
for Counter:= 1 to 5 do
  (*statement*);

Decrementing (counting backwards) is using downto keyword instead of to, as in:

for Counter:= 5 downto 1 do
  (*statement*);

The numeric range for loop varies somewhat more.

1972: C, C++

[edit]
for (initialization; condition; increment/decrement)
    statement

The statement is often a block statement; an example of this would be:

//Using for loops to add numbers 1 - 5
int sum = 0;
for (int i = 1; i <= 5; ++i) {
    sum += i;
}

The ISO/IEC 9899:1999 publication (commonly known as C99) also allows initial declarations in for loops. All three sections in the for loop are optional, with an empty condition equivalent to true.

1972: Smalltalk

[edit]
1 to: 5 do: [ :counter | "statements" ]

Contrary to other languages, in Smalltalk a for loop is not a language construct but is defined in the class Number as a method with two parameters, the end value and a closure, using self as start value.

1980: Ada

[edit]
for Counter in 1 .. 5 loop
   -- statements
end loop;

The exit statement may be used to exit the loop. Loops can be labeled, and exit may leave a specifically labeled loop in a group of nested loops:

Counting:
    For Counter in 1 .. 5 loop
   Triangle:
       for Secondary_Index in 2 .. Counter loop
          -- statements
          exit Counting;
          -- statements
       end loop Triangle;
    end loop Counting;

1980: Maple

[edit]

Maple has two forms of for loop, one for iterating over a range of values, and the other for iterating over the contents of a container. The value range form is as follows:

for i from f by b to t while w do
    # loop body
od;

All parts except do and od are optional. The for I part, if present, must come first. The remaining parts (from f, by b, to t, while w) can appear in any order.

Iterating over a container is done using this form of loop:

for e in c while w do
    # loop body
od;

The in c clause specifies the container, which may be a list, set, sum, product, unevaluated function, array, or object implementing an iterator.

A for loop may be terminated by od, end, or end do.

1982: Maxima CAS

[edit]

In Maxima CAS, one can use also integer values:

for x:0.5 step 0.1 thru 0.9 do
    /* "Do something with x" */

1982: PostScript

[edit]

The for loop, written as [initial] [increment] [limit] { ... } for initializes an internal variable, and executes the body as long as the internal variable is not more than the limit (or not less, if the increment is negative) and, at the end of each iteration, increments the internal variable. Before each iteration, the value of the internal variable is pushed onto the stack.[5]

1 1 6 {STATEMENTS} for

There is also a simple repeat loop. The repeat-loop, written as X { ... } repeat, repeats the body exactly X times.[6]

5 { STATEMENTS } repeat

1983: Ada 83 and above

[edit]
procedure Main is
  Sum_Sq : Integer := 0;
begin
  for I in 1 .. 9999999 loop
    if Sum_Sq <= 1000 then
      Sum_Sq := Sum_Sq + I**2
    end if;
  end loop;
end;

1984: MATLAB

[edit]
for n = 1:5
     -- statements
end

After the loop, n would be 5 in this example.

As i is used for the Imaginary unit, its use as a loop variable is discouraged.

1987: Perl

[edit]
for ($counter = 1; $counter <= 5; $counter++) { # implicitly or predefined variable
    # statements;
}
for (my $counter = 1; $counter <= 5; $counter++) { # variable private to the loop
    # statements;
}
for (1..5) { # variable implicitly called $_; 1..5 creates a list of these 5 elements
    # statements;
}
statement for 1..5; # almost same (only 1 statement) with natural language order
for my $counter (1..5) { # variable private to the loop
    # statements;
}

"There's more than one way to do it" is a Perl programming motto.

1988: Mathematica

[edit]

The construct corresponding to most other languages' for loop is named Do in Mathematica.

Do[f[x], {x, 0, 1, 0.1}]

Mathematica also has a For construct that mimics the for loop of C-like languages.

For[x= 0 , x <= 1, x += 0.1,
    f[x]
]

1989: Bash

[edit]
# first form
for i in 1 2 3 4 5
do
    # must have at least one command in a loop
    echo $i  # just print the value of i
done
# second form
for (( i = 1; i <= 5; i++ ))
do
    # must have at least one command in a loop
    echo $i  # just print the value of i
done

An empty loop (i.e., one with no commands between do and done) is a syntax error. If the above loops contained only comments, execution would result in the message "syntax error near unexpected token 'done'".

1990: Haskell

[edit]

In Haskell98, the function mapM_ maps a monadic function over a list, as

mapM_ print [4, 3 .. 1]
-- prints
-- 4
-- 3
-- 2
-- 1

The function mapM collects each iteration result in a list:

result_list <- mapM (\ indx -> do{ print indx; return (indx - 1) }) [1..4]
-- prints
-- 1
-- 2
-- 3
-- 4
-- result_list is [0,1,2,3,4]

Haskell2010 adds functions forM_ and forM, which are equivalent to mapM_ and mapM, but with their arguments flipped:

forM_ [0..3] $ \ indx -> do
    print indx
-- prints
-- 0
-- 1
-- 2
-- 3

result_list <- forM ['a'..'d'] $ \ indx -> do
    print indx
    return indx
-- prints
-- 'a'
-- 'b'
-- 'c'
-- 'd'
-- result_list is ['a','b','c','d']

When compiled with optimization, none of the expressions above will create lists. But, to save the space of the [1..5] list if optimization is turned off, a forLoop_ function could be defined as

import Control.Monad as M

forLoop_ :: Monad m => a -> (a -> Bool) -> (a -> a) -> (a -> m ()) -> m ()
forLoop_ startIndx test next f = theLoop startIndx
  where
    theLoop indx = M.when (test indx) $ do
        f indx
        theLoop (next indx)

and used as

forLoopM_ (0::Int) (< len) (+1) $ \indx -> do
    -- statements

1991: Oberon-2, Oberon-07, Component Pascal

[edit]
FOR Counter:= 1 TO 5 DO
  (* statement sequence *)
END

In the original Oberon language, the for loop was omitted in favor of the more general Oberon loop construct. The for loop was reintroduced in Oberon-2.

1991: Python

[edit]

Python does not contain the classical for loop, rather a foreach loop is used to iterate over the output of the built-in range() function which returns an iterable sequence of integers.

for i in range(1, 6):  # gives i values from 1 to 5 inclusive (but not 6)
    # statements
    print(i)
# if we want 6 we must do the following
for i in range(1, 6 + 1):  # gives i values from 1 to 6
    # statements
    print(i)

Using range(6) would run the loop from 0 to 5.

When the loop variable is not needed, it is common practice to use an underscore (_) as a placeholder. This convention signals to other developers that the variable will not be used inside the loop. For example:

for _ in range(5):
    print("Hello")

This will print “Hello” five times without using the loop variable.

1993: AppleScript

[edit]
repeat with i from 1 to 5
	-- statements
	log i
end repeat

It can also iterate through a list of items, similar to what can be done with arrays in other languages:

set x to {1, "waffles", "bacon", 5.1, false}
repeat with i in x
	log i
end repeat

A exit repeat may also be used to exit a loop at any time. Unlike other languages, AppleScript currently has no command to continue to the next iteration of a loop.

1993: Crystal

[edit]
for i = start, stop, interval do
  -- statements
end

So, this code

for i = 1, 5, 2 do
  print(i)
end

will print:

1 3 5

A for loop can also loop through a table using

ipairs()

to iterate numerically through arrays and

pairs()

to iterate randomly through dictionaries.

Generic for loop making use of closures:

for name, phone, and address in contacts() do
  -- contacts() must be an iterator function
end

1995: ColdFusion Markup Language (CFML)

[edit]

Script syntax

[edit]

Simple index loop:

for (i = 1; i <= 5; i++) {
	// statements
}

Using an array:

for (i in [1,2,3,4,5]) {
	// statements
}

Using a list of string values:

loop index="i" list="1;2,3;4,5" delimiters=",;" {
	// statements
}

The above list example is only available in the dialect of CFML used by Lucee and Railo.

Tag syntax

[edit]

Simple index loop:

<cfloop index="i" from="1" to="5">
	<!--- statements --->
</cfloop>

Using an array:

<cfloop index="i" array="#[1,2,3,4,5]#">
	<!--- statements --->
</cfloop>

Using a "list" of string values:

<cfloop index="i" list="1;2,3;4,5" delimiters=",;">
	<!--- statements --->
</cfloop>

1995: Java

[edit]
for (int i = 0; i < 5; i++) {
    //perform functions within the loop;
    //can use the statement 'break;' to exit early;
    //can use the statement 'continue;' to skip the current iteration
}

For the extended for loop, see Foreach loop § Java.

1995: JavaScript

[edit]

JavaScript supports C-style "three-expression" loops. The break and continue statements are supported inside loops.

for (var i = 0; i < 5; i++) {
    // ...
}

Alternatively, it is possible to iterate over all keys of an array.

for (var key in array) {  // also works for assoc. arrays
    // use array[key]
    ...
}

1995: PHP

[edit]

This prints out a triangle of *

for ($i = 0; $i <= 5; $i++) {
    for ($j = 0; $j <= $i; $j++) {
        echo "*";
    }
    echo "<br />\n";
}

1995: Ruby

[edit]
for the counter in 1..5
  # statements
end

5.times do |counter|  # counter iterates from 0 to 4
  # statements
end

1.upto(5) do |counter|
  # statements
end

Ruby has several possible syntaxes, including the above samples.

1996: OCaml

[edit]

See expression syntax.[7]

 (* for_statement:= "for" ident '='  expr  ( "to" ∣  "down to" ) expr "do" expr "done" *)

for i = 1 to 5 do
    (* statements *)
  done ;;

for j = 5 down to 0 do
    (* statements *)
  done ;;

1998: ActionScript 3

[edit]
for (var counter:uint = 1; counter <= 5; counter++){
    //statement;
}

2008: Small Basic

[edit]
For i = 1 To 10
    ' Statements
EndFor

2008: Nim

[edit]

Nim has a foreach-type loop and various operations for creating iterators.[8]

for i in 5 .. 10:
  # statements

2009: Go

[edit]
for i := 0; i <= 10; i++ {
    // statements
}

2010: Rust

[edit]
for i in 0..10 {
    // statements
}

2011: Kotlin

[edit]
for (i in 1..10) {
    // statements
}


2012: Julia

[edit]
for j = 1:10
    # statements
end

See also

[edit]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
In , a for loop is a fundamental statement that allows a block of code to be executed repeatedly, typically a fixed number of times or over the elements of a collection, using an variable for indexing or . It is designed to simplify repetitive tasks by combining initialization, condition checking, and incrementation within a single construct, making it more concise than equivalent while loops in many cases. Early examples of loop constructs include Fortran's DO loop from 1957. The for loop keyword originated in high-level programming languages with its initial formalization in ALGOL 58, followed by significant refinement in ALGOL 60, where it was introduced as a versatile iteration mechanism supporting assignments, step-until increments, or conditional while clauses. This design influenced later imperative languages like C, Pascal, and Java. Syntactically, for loops vary across languages but generally follow a pattern of initialization, condition, and update, as exemplified -style syntax:

c

for (initialization; condition; update) { // body executed repeatedly }

for (initialization; condition; update) { // body executed repeatedly }

This form, popularized (1972), initializes a counter, tests a condition before each , and updates the counter after the body executes. In contrast, Python's for loop iterates directly over iterables like lists or ranges, emphasizing readability over explicit counters:

python

for item in iterable: # body executed for each item

for item in iterable: # body executed for each item

Such variations reflect language paradigms, with imperative languages favoring counter-based loops for performance in array traversal and declarative styles prioritizing iteration over sequences. For loops are essential for algorithms involving repetition, such as summing array elements, generating sequences, or simulating processes, and their efficiency depends on avoiding common pitfalls like off-by-one errors or infinite loops. They remain a cornerstone of procedural and object-oriented programming, enabling scalable code for data processing in fields from scientific computing to web development.

Definition and Fundamentals

Core Concept and Syntax

A for loop is a repetition control structure in programming that executes a block of code a predetermined number of times, typically managed by a counter variable to iterate through a known range or sequence. This structure provides a concise way to handle repetitive tasks, distinguishing it from indefinite loops like while statements by its emphasis on a fixed count. The basic pseudocode syntax for a traditional for loop follows the form:

for (initialization; condition; increment) { body }

for (initialization; condition; increment) { body }

Here, the initialization statement sets the starting value of the loop counter (e.g., setting a variable to zero), executed only once at the beginning. The condition is evaluated before each iteration to determine if the loop should continue; if false, execution proceeds after the loop. The increment (or update) modifies the counter after each execution of the body, advancing the loop toward termination. For loops are commonly used to iterate over sequences such as arrays or numeric ranges, allowing access to elements without explicit manual counter adjustments in certain implementations. Historically, the for loop originated as a mechanism to simplify repetitive calculations in early , with the foundational "für" construct introduced by Heinz Rutishauser in his 1951 algorithmic Superplan.

Initialization, Condition, and Iteration

In the traditional for loop construct, the initialization clause is executed exactly once before the loop body begins, typically to declare and set an initial value for a loop control variable, such as a counter starting at zero. This step ensures the loop begins from a defined state, often involving simple assignment like i = 0 in languages like C. The condition clause, a boolean expression, is evaluated prior to each iteration of the loop body; if it evaluates to true (or non-zero in languages without explicit booleans), the body executes, but if false, the loop terminates immediately without entering or continuing the body. For instance, a condition such as i < n checks whether the counter remains within the desired bounds, controlling the number of iterations based on the problem's requirements. Following the execution of the loop body, the iteration clause—also known as the update or increment—is performed to modify the loop control variable, preparing it for the next condition check. This often involves incrementing the counter, as in i++, but can include more complex updates like i += 2 for stepping through values at intervals. The full execution flow proceeds as: initialization (once), condition evaluation, body (if true), iteration, then repeat from condition until false. These clauses collectively manage the loop's lifecycle, with the counter variable's role in initialization, testing, and updating detailed further in discussions of loop counters. Omitting the initialization clause assumes prior setup of the control variable, while an always-true condition can lead to unbounded execution, though such cases are handled through other control mechanisms. In the C programming language, for example, the syntax for (i = 0; i < 10; i++) { /* body */ } illustrates this flow, where all clauses are optional but the structure enforces the specified order per ISO/IEC 9899 standards.

Variations of For Loops

Traditional Indexed For Loops

Traditional indexed for loops represent the classic form of the for loop construct, featuring explicit initialization of a counter variable, a condition that checks against predefined bounds, and an increment or update expression to advance the counter after each iteration. This structure is prevalent in imperative programming languages such as , C++, , and , where the syntax typically follows the pattern of for (initialization; condition; increment) { body }. The initialization sets the starting value of the index (often 0 for zero-based arrays), the condition evaluates to true for continuation (e.g., index less than array length), and the increment updates the index (e.g., i++). These loops are commonly applied in scenarios requiring direct access to array elements via numerical indices or performing repetitive numerical operations, such as summing values in an array or processing fixed-size datasets. For instance, in array traversal, the loop iterates over each element by referencing array[i], enabling operations like accumulation or transformation. In mathematical summations, a typical implementation might initialize a sum to zero and add array[i] within the loop body until the bounds are reached. This form is particularly suited to scientific computing tasks where precise iteration over known ranges is essential. The primary advantages of traditional indexed for loops include precise control over the iteration process, allowing developers to customize step sizes, reverse direction, or skip elements as needed, which supports flexible traversal patterns beyond simple sequential access. They offer conceptual simplicity, making them straightforward for expressing definite iterations in parallel contexts, such as distributed computing where static analysis of affine indices can optimize communication overhead. Additionally, their efficiency shines with fixed-size collections, as the explicit bounds and increments facilitate compiler optimizations without runtime overhead from iterators. However, these loops can be verbose, necessitating manual management of initialization, conditions, and increments, which increases code length compared to higher-level abstractions. They are prone to errors, particularly off-by-one mistakes where the index exceeds array bounds or misses elements at the endpoints, a common pitfall in array-based operations. This sequential indexing also inherently suggests ordered execution, potentially complicating parallelization without additional transformations. A representative pseudocode example for processing an array via indexing is:

for (int i = 0; i < length; i++) { process(element[i]); }

for (int i = 0; i < length; i++) { process(element[i]); }

This iterates from the first to the last element, providing direct positional access.

Iterator-Based For Loops

Iterator-based for loops, also known as enhanced for loops or foreach loops, provide a syntax for traversing collections or iterables without explicitly managing indices or counters. The general form is for (element : collection), where each element of the collection is sequentially assigned to the loop variable for processing within the loop body. This construct abstracts away the traditional initialization, condition, and increment steps of indexed loops, focusing instead on the elements themselves. The mechanism relies on iterator objects or enumerator methods provided by the collection. In languages like Java, the enhanced for loop implicitly calls the iterator() method on collections implementing the Iterable interface, advancing through elements via hasNext() and next() until exhausted. Similarly, in C#, the foreach statement invokes GetEnumerator() on types implementing IEnumerable or IEnumerable<T>, using the enumerator's MoveNext() method and Current property to yield elements sequentially. Python's for loop operates on any iterable by calling its __iter__() method to obtain an iterator, which supplies elements one by one through __next__(). In C++, the range-based for loop (introduced in C++11) uses the range's begin() and end() functions to establish iterators, dereferencing them to access elements in order. This iterator-driven approach ensures sequential access while hiding the underlying traversal logic. These loops find primary applications in object-oriented and languages for iterating over data structures such as lists, sets, arrays, and maps. For instance, in , they are used to process elements in ArrayList or HashSet without needing explicit iteration code. Python employs them for traversing sequences like lists or dictionaries (via .items() for key-value pairs). C# applies foreach to collections like List<T> or arrays, and C++ uses range-based loops for standard containers such as std::vector or std::string. This makes them ideal for tasks like summing values, filtering elements, or performing operations on each item in a collection, promoting code that works polymorphically across compatible types. Key benefits include reduced by eliminating manual index management, which minimizes errors like off-by-one bounds issues common in traditional loops. They enhance and , allowing developers to focus on element processing rather than traversal mechanics, and support polymorphism by operating uniformly on any iterable or enumerable type. For example, in Python:

python

words = ['cat', 'window', 'defenestrate'] for w in words: print(w, len(w))

words = ['cat', 'window', 'defenestrate'] for w in words: print(w, len(w))

This outputs the length of each word without indexing. In Java:

java

int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for (int item : numbers) { [System](/page/System).out.println("Count is: " + item); }

int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for (int item : numbers) { [System](/page/System).out.println("Count is: " + item); }

Such examples demonstrate cleaner syntax compared to indexed alternatives. However, iterator-based for loops offer less fine-grained control than indexed variants, as they typically enforce sequential forward traversal without easy access to order modification, element skipping, or direct index retrieval. Modifying the underlying collection during can lead to runtime errors or , such as concurrent modification exceptions in or skipped elements in Python. They are also less suitable for multi-dimensional structures requiring nested indexing, like jagged arrays, where explicit coordinates are needed. In C++, lifetime issues with temporary ranges were a concern before extensions. These limitations make them best suited for simple, linear traversals rather than complex navigation scenarios.

Vectorized and Implicit For Loops

Vectorized and implicit for loops represent an optimization paradigm in programming, particularly in numerical and scientific , where iteration over collections of —such as arrays or vectors—is performed without explicit loop constructs or visible counters. Instead, these loops rely on or features that apply operations element-wise across entire data structures in a single statement, implicitly handling the repetition. This approach contrasts with traditional explicit loops by shifting the iteration logic to optimized, low-level implementations, often executed in compiled code rather than interpreted loops. The mechanism underlying vectorized and implicit loops typically involves array and universal functions (ufuncs) in libraries like , where operations on arrays of compatible shapes are automatically expanded to match dimensions without copying data or using explicit indices. For instance, in , adding a scalar to an array implicitly applies the addition to each element, leveraging C-level loops for efficiency. Similarly, MATLAB's vectorization revises scalar-oriented code into matrix and vector operations, such as A + B for element-wise addition of matrices, which the interpreter processes without user-defined loops. These implementations often harness SIMD () instructions available in modern CPUs, allowing simultaneous processing of multiple data elements in a single operation, as supported by compilers like Intel's oneAPI DPC++/C++. In applications such as scientific and , vectorized loops enable concise expressions for bulk operations, like computing the sum of an with np.sum(A) in , which replaces a manual loop accumulating values element by element. This is prevalent in fields requiring high-throughput , where functions like element-wise multiplication or statistical aggregations process large datasets efficiently without per-element in user code. In , vector arithmetic supports implicit , as in x + y for two vectors, avoiding explicit loops like for(i in 1:length(x)) { result[i] <- x[i] + y[i] }, and functions like sapply extend this to more complex transformations over sequences. The primary advantages of vectorized and implicit for loops include substantial performance gains—often orders of magnitude faster than interpreted loops due to reduced overhead and SIMD utilization—and improved code readability through succinct syntax for mathematical operations on aggregates. For example, MATLAB documentation highlights that vectorized code often runs much faster than equivalent looped versions for large arrays by minimizing interpretive steps. However, drawbacks include restrictions to operations compatible with array data types, potential memory inefficiencies from temporary arrays in broadcasting, and obscured performance bottlenecks, as the implicit nature may prevent fine-tuned optimizations for irregular data patterns.

Loop Counters and Variables

Role and Management of Counters

In a for loop, the counter plays a central role in tracking iteration progress and enforcing finite execution by maintaining state across loop cycles. It is typically initialized to a starting value, such as zero for ascending sequences, and incremented or updated after each body execution, while being tested against a boundary condition before each iteration to determine continuation. This mechanism ensures controlled repetition, as seen in standard definitions where the counter advances from a low bound to a high bound, preventing unbounded runs. Management of the counter begins with its declaration, commonly as an integer type to support exact arithmetic, followed by initialization in the loop's opening clause to set the initial state. The update occurs via the iteration clause, often using increment operators like ++ for sequential progression or custom logic for non-linear steps, ensuring the counter reflects cumulative advancement. These operations are executed in a fixed sequence—initialization once, then repeated condition checks and updates— to synchronize iteration with the program's intent. Best practices emphasize selecting appropriate types for reliability: unsigned integers, such as size_t in C for non-negative counts, align with container sizes and array lengths, reducing comparison mismatches and supporting large ranges without sign-related artifacts. Floating-point types should be avoided as counters due to precision limitations that can cause erratic iteration counts from rounding errors. Explicit bounds and pre-computed limits further safeguard against excessive iterations. Common pitfalls arise from integer overflow, where prolonged loops push the counter beyond its type's maximum, triggering wrap-around that may yield undefined behavior, skipped iterations, or infinite execution in signed types. Mismatches between signed and unsigned counters exacerbate this, as implicit promotions can invert comparisons and fail to terminate loops correctly when interfacing with unsigned sizes like array lengths. For instance, in C, declaring for (size_t i = 0; i < n; ++i) mitigates overflow for large n by leveraging the unsigned nature of size_t, which wraps predictably without invoking undefined behavior on overflow.

c

for (size_t i = 0; i < n; ++i) { // Loop body }

for (size_t i = 0; i < n; ++i) { // Loop body }

Scope, Lifetime, and Modification

In modern programming languages such as C++ and JavaScript, the scope of a for loop's control variable is typically limited to the block of the loop itself when declared within the loop's initialization clause, ensuring it is not accessible outside the loop to prevent unintended reuse or shadowing issues. For instance, in C++ (since C++98), a variable declared in the for loop's init-statement has its scope confined to the entire for statement, including the condition, increment, and body, but it is destroyed upon loop completion. Similarly, in JavaScript, using let for the loop variable enforces block scoping, making it inaccessible after the loop, whereas the older var keyword results in function scoping, allowing post-loop access to the variable's final value. In contrast, older languages like treat for loop control variables with program-wide scope, where the variable persists throughout the entire program and retains its final value after the loop ends, reflecting the absence of block scoping in early implementations. The lifetime of a for loop's control variable generally begins at its initialization (either explicitly before or within the loop header) and extends until the end of its scope or explicit reassignment/destruction, with post-loop accessibility depending on the scoping rules: inaccessible in block-scoped modern languages but available in broader-scoped older ones like . Modification of the loop control variable within the body is permitted in imperative languages, allowing manual adjustments such as incrementing or decrementing beyond the loop's update expression (e.g., i -= 1 inside a loop incrementing i++), but this can lead to unintended behavior like infinite loops if the change violates the loop condition prematurely. In functional languages like , traditional mutable for loops do not exist; instead, iteration is achieved through recursion or higher-order functions with immutable bindings, avoiding mutable counters altogether to maintain referential transparency.

javascript

// JavaScript example: block scoping with let for (let i = 0; i < 5; i++) { console.log(i); // i is accessible here } // console.log(i); // ReferenceError: i is not defined (block-scoped)

// JavaScript example: block scoping with let for (let i = 0; i < 5; i++) { console.log(i); // i is accessible here } // console.log(i); // ReferenceError: i is not defined (block-scoped)

This scoping and mutability model influences program reliability, as block scoping in modern languages reduces bugs from variable leakage, while broader scopes in legacy systems require careful management to avoid side effects.

Control and Semantics

Infinite and Unbounded Loops

Infinite and unbounded for loops are configured by omitting the loop condition or explicitly setting it to a value that always evaluates to true, resulting in continuous execution without automatic termination. In the C programming language, the syntax for(;;) omits the condition expression, which is treated as a non-zero constant equivalent to true, creating an endless loop unless interrupted by other control statements. This form is a standard idiom for indefinite iteration, as documented in the seminal reference on C. Such loops are commonly employed in patterns requiring persistent execution, such as event-driven waits in server applications where the loop monitors for incoming connections or events, or in simulations like game loops that continuously update states until an external signal halts them. For instance, a server might use for (initialization; ; update) to repeatedly check for network activity, processing requests in each iteration while incrementing a counter for logging purposes. However, infinite for loops pose significant risks, including resource exhaustion where repeated iterations consume CPU cycles, memory, or other system resources, potentially leading to program crashes, denial-of-service conditions, or system-wide performance degradation. Termination typically requires manual intervention, such as a break statement triggered by a specific condition, signal handling, or external process termination, emphasizing the need for careful design to avoid unintended endless execution. While equivalent to a while(true) construct in functionality, for loops are often preferred for infinite scenarios when counter-based progress tracking is desired, as the initialization and update clauses allow seamless integration of iteration variables without separate declarations. This preference stems from the structured nature of for loops, which encapsulate all loop control elements in one statement, as exemplified by the common macro #define forever for(;;) for readability. A typical guarded infinite for loop incorporates a conditional break to ensure safe termination, such as:

for(;;) { if (some_condition) break; process_data(); }

for(;;) { if (some_condition) break; process_data(); }

This pattern allows the loop to run indefinitely until the guard condition is met, balancing persistence with controlled exit.

Early Exit and Continuation Mechanisms

In programming languages that support , early exit and continuation mechanisms provide fine-grained control over loop execution, allowing developers to terminate or skip iterations based on conditions without relying solely on the loop's inherent structure. These mechanisms, primarily the break and continue statements, originated in early imperative languages and are now standard in many modern ones, enabling more efficient and readable code for tasks requiring conditional interruption. While they can be applied to potentially infinite loops to impose bounds, their primary role is in bounded iterations where premature adjustment is needed. The break statement immediately terminates the execution of the innermost enclosing loop, transferring control to the statement following the loop body. In a for loop, this exits after the current iteration's body, bypassing any remaining iterations, the update expression, and the condition check. For instance, in C, as described by Kernighan and Ritchie, break is used to exit when a negative value is encountered in an array traversal. Similarly, in Java, an unlabeled break ends the innermost for loop, such as when searching an array for a specific value like 12 at index 4. In Python, break exits the innermost for loop, for example, when a factor is found during a primality check. The continue statement skips the remainder of the current iteration in the innermost enclosing loop, advancing directly to the update expression (in a for loop) or the condition check, and then proceeding to the next iteration if applicable. This avoids executing subsequent code in the body for that iteration. In C, continue is employed to ignore negative elements when summing an array, jumping past the addition for those cases. Java's unlabeled continue, for example, skips non-matching characters when counting occurrences of 'p' in a string, ensuring only relevant iterations contribute to the count. Python uses continue to bypass odd numbers in a loop printing even ones, streamlining output without nested conditionals. In nested for loops, both break and continue typically affect only the innermost loop unless the language supports labeled statements. In C and Python, an unlabeled break or continue impacts solely the immediate enclosing loop, requiring alternative structures like functions or flags for outer control. Java, however, allows labeled break and continue to target outer loops explicitly; for instance, a labeled break "search" in nested for loops exits the outer loop upon finding a target at position (1, 0), while a labeled continue "test" skips to the next outer iteration if inner matches fail. These mechanisms are particularly valuable for optimization in search operations and error handling in batch processing. Break enables early termination in linear searches, halting iteration once a target is found to avoid unnecessary computations—for example:

c

for (int i = 0; i < n; i++) { if (arr[i] == target) { break; // Exit upon finding the first match } }

for (int i = 0; i < n; i++) { if (arr[i] == target) { break; // Exit upon finding the first match } }

This reduces time complexity in the average case for unsorted data. Continue facilitates skipping invalid or erroneous items in iterative data processing, such as ignoring malformed records in a file parse without aborting the entire loop, thus maintaining robustness in batch tasks.

Bounds Adjustment and Range Handling

In programming languages, bounds adjustment refers to the dynamic modification of the loop's upper or lower limits during execution, typically by altering the condition variable or bound expressions within the loop body. For instance, in C++, a for loop like for (int i = 0; i < n; ++i) allows modification of n inside the body, such as decrementing n to reduce iterations, but this can lead to unpredictable behavior if the change affects the condition evaluation inconsistently across iterations. Similarly, in Java, the for loop's condition can be influenced by updating bound variables mid-execution, enabling adaptive iteration spaces like shrinking arrays during processing. However, such adjustments are generally discouraged due to their potential to complicate code readability and introduce errors. Modifying loop bounds carries significant risks, including infinite loops or skipped iterations, as the compiler or runtime may not anticipate changes to the termination condition. In C++, altering the loop counter or bound variable can violate the forward progress guarantee, potentially resulting in undefined behavior for non-terminating loops without observable side effects since C++26. For example, if a decrement to the upper bound occurs unevenly, the loop might never satisfy the condition, causing endless execution; conversely, excessive reductions could bypass intended iterations. Languages like Pascal mitigate this by prohibiting direct assignment to the control variable in a for-to-do loop, ensuring the counter remains unaltered and the loop executes exactly as bounded, with any attempted modification raising a compile-time error. Range specification in for loops defines the iteration space through inclusive or exclusive bounds, determining whether endpoints are included in the sequence. In Python's iterator-based for loop using the range() function, the start is inclusive (defaulting to 0), while the stop is exclusive, producing sequences like range(1, 6) yielding 1 through 5; this half-open interval convention avoids off-by-one errors in array indexing. Contrastingly, Visual Basic .NET's For...Next statement uses inclusive bounds, executing while the counter is less than or equal to (or greater than or equal to, for negative steps) the end value, such as For i As Integer = 1 To 10 including both 1 and 10. Mishandling these conventions, such as assuming inclusivity in an exclusive system, risks infinite loops if the step fails to reach or surpass the bound appropriately. Step sizes extend range handling by allowing increments beyond 1, facilitating efficient traversal of sparse or patterned data. Python's range(start, stop, step) supports arbitrary integer steps, including negative values for descending sequences, as in range(0, 10, 2) producing 0, 2, 4, 6, 8; a step of zero raises a ValueError to prevent infinite loops. In Visual Basic .NET, the optional Step clause defaults to 1 but permits fractions or negatives, like For i As Double = 10 To 0 Step -0.5, decrementing inclusively to include 0. C++ achieves variable steps via the update expression, such as for (int i = 0; i < 100; i += 5), skipping every four values for performance in large ranges. Advanced range handling includes reverse iteration through decrementing counters, often via dedicated syntax to ensure safe traversal. Pascal's for-downto-do construct reverses inclusively with a step of -1, as in for i := 10 downto 1 do, executing from 10 to 1 without modifiable bounds to avoid skips. Python emulates this with negative steps in range(), like range(10, 0, -1) yielding 10 down to 1 (exclusive of 0), while Java and C++ use for (int i = n-1; i >= 0; --i) for equivalent descending exclusive bounds. Non-linear ranges, such as logarithmic or custom progressions, are typically implemented by adjusting steps dynamically in languages permitting bound modifications, though this heightens risks of incomplete coverage if the sequence does not align with the termination condition.

Comparisons with Other Constructs

Equivalence to While Loops

In many programming languages, such as and C++, the traditional for loop with initialization, condition, and update clauses is semantically equivalent to a constructed by performing the initialization once before the loop, evaluating the condition at the start of each iteration, executing the loop body, and then performing the update. Specifically, a for loop of the form for (init; cond; update) { body } expands to init; while (cond) { body; update; }, where the while loop checks the condition before entering the body, ensuring identical execution flow for finite iterations when the condition eventually falsifies. This equivalence can be demonstrated through structural expansion and , showing that all behaviors of a for loop—whether finite termination upon condition failure or infinite looping if the condition remains true and the update does not alter it—are directly mappable to a . For instance, an infinite for loop like for (;; ) { body } (with omitted condition and update) is equivalent to while (1) { body }, as the empty condition defaults to true in semantics, and both constructs repeat indefinitely unless interrupted by other control statements. The mapping preserves termination properties: if the for loop halts after k iterations due to the condition becoming false after the k-th update, the does the same by placing the update after the body but before the next condition check. For loops are typically preferred when the number of iterations is known in advance, such as traversing a fixed-size array or performing a predetermined count of operations, due to their concise syntax that groups initialization, condition, and update in one place. In contrast, while loops are favored for dynamic conditions where the iteration count is uncertain, like processing input until end-of-file or waiting for a user event, as they emphasize the condition without implying a counter-based structure. A key limitation of rewriting for loops as while loops is that the while construct lacks a dedicated update clause, necessitating manual placement of the update statement within the body, which can lead to errors if forgotten or misplaced (e.g., inside conditional branches). For example, the C for loop int i = 0; for (i = 0; i < 5; i++) { x += i; } transforms to int i = 0; while (i < 5) { x += i; i++; }, where the increment i++ must be explicitly added after the body to avoid an infinite loop.

Relation to Do-While and Recursive Alternatives

The for loop evaluates its condition prior to the first iteration, allowing for the possibility of zero executions if the condition is false from the outset. In contrast, the do-while loop performs the condition check after executing the body at least once, ensuring a minimum of one iteration regardless of the initial condition value. This fundamental difference in timing—pre-iteration for for loops versus post-iteration for do-while—arises from their syntactic and semantic designs in languages like and C++, where the for loop's structure integrates initialization, condition, and update into a single construct equivalent to a while loop with prefixed initialization. Converting between these constructs requires careful adjustment of the condition placement to preserve behavior. For instance, a do-while loop without prior initialization, such as do { body; update; } while (cond);, can be emulated in a for loop by using an empty initialization, condition, and update, placing the update inside the body before the post-body check: for (;; ) { body; update; if (!cond) break; }. This approach inverts the test timing while maintaining the guaranteed first execution, though it introduces an explicit break for early exit, which may alter readability in imperative languages. In functional programming paradigms, recursive functions, particularly those employing tail recursion, provide an alternative to traditional by simulating iteration without mutable state. Tail recursion occurs when the recursive call is the final operation in the function, enabling compilers or interpreters to optimize it into an iterative loop via tail call optimization (TCO), which reuses the current stack frame instead of allocating new ones. This equivalence allows tail-recursive functions to achieve the constant space complexity of loops while adhering to functional purity. A seminal formalization of proper tail recursion in Scheme, which influences many functional languages, defines it as recursion where no operations follow the recursive call, ensuring space efficiency comparable to iteration. For example, in , a tail-recursive sum function mimics a for loop over a :

sum' :: Num a => [a] -> a sum' xs = sumHelper xs 0 where sumHelper [] acc = acc sumHelper (x:xs) acc = sumHelper xs (acc + x)

sum' :: Num a => [a] -> a sum' xs = sumHelper xs 0 where sumHelper [] acc = acc sumHelper (x:xs) acc = sumHelper xs (acc + x)

Here, the recursive call to sumHelper is in tail position, allowing the Haskell compiler to optimize it to a loop-like with O(1) space. Such patterns are common in the Prelude for operations like list folding, where replaces explicit looping constructs absent in the language. Recursion, including tail variants, is particularly suited for problems with inherent hierarchical structure, such as tree traversals, where a for loop would require awkward auxiliary stacks or indices. However, without TCO, general recursion risks stack overflow from excessive depth, consuming O(n) space for n calls, whereas iterative for loops maintain constant stack usage by avoiding function calls altogether. Languages like Haskell mandate TCO for tail recursion, mitigating this trade-off and making recursion viable for large-scale iteration, though it may introduce slight overhead in non-optimized environments compared to native loops.

Historical Evolution

Origins in Early Languages (1950s-1960s)

The for loop construct emerged in the late 1950s as programming languages sought to simplify repetitive operations common in scientific and business computing, moving away from the unstructured jumps prevalent in assembly languages. In 1957, introduced the DO loop, the earliest iteration mechanism resembling a modern for loop, designed to automate index calculations for numerical computations that previously required manual manipulation of registers in . The syntax was DO n i = m1, m2 (optionally with step m3), where n labeled the terminal statement, i was the control variable, m1 the start, m2 the end, and m3 the increment (defaulting to 1); execution proceeded from the DO to statement n, after which control passed to the next statement. This innovation enabled fixed counts, directly supporting mathematical processes like summations and array traversals, and was optimized by the to generate efficient code comparable to hand-optimized assembly. Building on FORTRAN's foundation, formalized a more expressive for statement in , emphasizing clarity and generality for algorithmic description. The syntax allowed for V := E1 (E2) E3 do S, where V was the variable, E1 the initial value, E2 the step (optional, default 1), E3 the limit, and S the body; an alternative list form assigned successive values from a comma-separated sequence. For example, for I := 1 (1) 10 do P(I) iterated I from 1 to 10, executing procedure P each time, equivalent to a conditional loop but more concise. This design drew inspiration from mathematical notation for sequences, promoting readable expressions for bounded repetition in scientific algorithms while replacing ad-hoc chains. By 1960, adapted the concept for with the PERFORM VARYING statement, tailored to business applications involving table scans and report generation. The syntax was PERFORM paragraph VARYING counter FROM initial BY increment UNTIL condition, executing the named repeatedly while incrementing the counter until the condition held true. This allowed flexible bounds based on data conditions rather than fixed counts, addressing repetitive file handling that assembly required explicit indexing for, and integrated seamlessly with COBOL's English-like prose for non-scientific users. In 1964, two influential languages further refined the for loop for accessibility and versatility. BASIC's FOR...NEXT construct, FOR I = 1 TO 10 ... NEXT I, provided a simple, line-numbered iteration for educational and interactive use, with implicit step 1 and optional STEP clause, enabling beginners to handle loops without complex syntax. Similarly, PL/I's DO statement, DO i = 1 TO 10; ... END;, combined FORTRAN-like indexing with block structure, supporting variable steps and conditions within a compound statement for robust scientific and . These developments underscored the for loop's role in abstracting away low-level repetition control, fostering structured code influenced by summation sigma notation in .

Development in Structured Programming (1970s-1980s)

In the 1970s, principles, which emphasized clear through constructs like bounded , significantly influenced the evolution of the for loop, building on earlier procedural foundations to promote readability and maintainability in code. Niklaus Wirth's Pascal, introduced in 1970, exemplified this shift with its for loop syntax designed for teaching and safe . The construct used the form for variable := initial_value to final_value do statement, where the was implicitly immutable during execution, preventing unintended modifications and ensuring predictable bounds. This feature aligned with 's avoidance of unstructured jumps, making Pascal a cornerstone for educational and . By 1972, Dennis Ritchie's C language introduced a more flexible for loop that became a model for portability across systems. The syntax for (expression1; expression2; expression3) statement allowed optional initialization, condition, and increment steps, enabling concise expression of initialization, testing, and updating in a single line while supporting infinite loops if the condition was omitted. This design, rooted in C's development for Unix at , prioritized efficiency and expressiveness for low-level programming, rapidly gaining adoption in operating systems and embedded applications due to its balance of control and simplicity. That same year, Alan Kay's Smalltalk pioneered object-oriented iteration with a block-based for loop, reflecting the language's emphasis on message-passing and encapsulation. The syntax 1 to: 10 do: [:i | statements] sent a do: message to a numeric range, passing each value to a closure (block) for execution, which integrated seamlessly with Smalltalk's dynamic, everything-is-an-object . This approach facilitated higher-level abstractions, influencing later languages by treating loops as methods on collections rather than rigid control structures. The 1980 release of Ada, developed under U.S. Department of Defense sponsorship, advanced range-based iteration for safety-critical systems. Its for loop syntax for identifier in [reverse] discrete_range loop sequence_of_statements end loop iterated over a predefined discrete range (e.g., 1 .. 10), with the loop parameter acting as a constant to enforce bounds checking and prevent overflow errors. This design supported structured programming's goals of reliability, particularly in concurrent and real-time environments, by integrating and explicit scoping. Mid-1980s innovations extended for loops to specialized domains, with MATLAB's 1984 introduction providing a colon-based syntax for numerical computing: for k = 1:10 statements end. This allowed stepping through vectors or ranges efficiently, tailored for matrix operations in scientific applications. Similarly, Larry Wall's , released in 1987, added a foreach variant foreach variable (@array) { statements } for iterating over lists and arrays, enhancing text processing and scripting by simplifying data traversal without index management. These developments marked a trend toward the C-style for loop's ubiquity for its versatility in imperative languages, promoting code portability across platforms, while the emergence of foreach constructs addressed iterable collections, reducing error-prone indexing. Overall, for loops in this era enabled safer, more readable code in and emerging scripting contexts, underpinning the structured paradigm's dominance by minimizing bugs from unbounded .

Modern Implementations (1990s-2020s)

In the 1990s, introduced a standardized for loop syntax that became influential across object-oriented languages, featuring an initialization, condition, and update clause within parentheses. The basic form, for (int i = 0; i < n; i++) { ... }, allows precise control over iteration counters, while the enhanced for loop, added in 5 (2004) as for (Type t : collection) { ... }, simplifies iteration over collections by eliminating explicit indexing. This design emphasized readability and reduced common errors like off-by-one bounds, influencing subsequent languages. Python, first released in 1991, adopted an iterator-based for loop with the syntax for i in range(n): ..., which iterates over sequences like lists or the range generator without manual counter management. This approach promoted Pythonic expressiveness, treating loops as traversals of iterables rather than rigid counters. Complementing explicit loops, list comprehensions like [x for x in range(n)] emerged as concise, implicit alternatives for building collections, blending imperative and functional styles. JavaScript's for loop, from its 1995 origins, mirrored C-style syntax with for (let i = 0; i < n; i++) { ... }, using let for block-scoped variables introduced in ES6 (2015). The ES6 update added for...of, as in for (const value of iterable) { ... }, enabling iteration over arrays, strings, and other iterables without indices, enhancing safety by avoiding mutation during traversal. The 2000s saw Go (2009) unify looping under a single for keyword, with traditional form for i := 0; i < n; i++ { ... } and range-based for k, v := range slice { ... } for maps and slices, prioritizing simplicity and garbage collection for concurrency. Rust (2010) emphasized through for i in 0..n { ... }, where .. denotes exclusive ranges, and iterator chains like for item in vec.iter() { ... }, enforcing immutability by default to prevent data races. Kotlin (2011), building on JVM interoperability, used range syntax for (i in 1..10) { ... }, extended with downTo for descending iteration and step for increments, as in for (i in 10 downTo 1 step 2) { ... }, to boost expressiveness while maintaining type safety. Into the 2010s and 2020s, Swift (2014) refined range iteration with for i in 0..<n { ... }, using ..< for exclusive upper bounds, and introduced stride for custom steps: for i in stride(from: 0, to: n, by: 2) { ... }, integrating seamlessly with optionals and collections for safer development. Julia (2012), focused on numerical computing, employed for i = 1:10 ... end, where : creates step ranges, alongside enhanced comprehensions like [i^2 for i=1:10] for vectorized operations. (2008), a systems , uses for i in 0..<n: ... with half-open intervals, supporting iterators for efficiency in contexts. These implementations addressed gaps in earlier designs by incorporating post-2012 languages like Swift and Kotlin. Modern for loops reflect broader trends toward safety via immutability (e.g., Rust's borrow checker preventing ) and concurrency support, such as Go's goroutines enabling parallel fors without locks. Expressiveness has grown through functional alternatives like map and reduce, reducing reliance on mutable loops, while iterator protocols ensure bounds-checked across ecosystems.

References

Add your contribution
Related Hubs
User Avatar
No comments yet.