## `for` -- for loop

#### Introduction

`for - end_for` is a repetition statement providing a loop for automatic iteration over a range of numbers or objects.

#### Call(s)

for i from start to stop <step stepwidth> do
body
end_for
`_for(i, start, stop, stepwidth, body)`
for i from start downto stop <step stepwidth> do
body
end_for
`_for_down(i, start, stop, stepwidth, body)`
for x in object do
body
end_for
`_for_in(x, object, body)`

#### Parameters

`i, x` | - | the loop variable: an identifier or a local variable (`DOM_VAR`) of a procedure
`start` | - | the starting value for `i`: a real number. This may be an integer, a rational number, or a floating point number.
`stop` | - | the stopping value for `i`: a real number. This may be an integer, a rational number, or a floating point number.
`stepwidth` | - | the step width: a positive real number. This may be an integer, a rational number, or a floating point number. The default value is 1.
`object` | - | an arbitrary MuPAD object
`body` | - | the body of the loop: an arbitrary sequence of statements

#### Returns

the value of the last command executed in the body of the loop. If no command was executed, the value `NIL` is returned. If the iteration range is empty, the void object of type `DOM_NULL` is returned.

#### Further Documentation

Chapter 16 of the MuPAD Tutorial.

#### Related Functions

`break`, `next`, `repeat`, `while`

#### Details

- When entering an incrementing loop

  `for i from start to stop step stepwidth do body end_for`,

  the assignment `i := start` is made. The body is executed with this value of `i` (the body may reassign a new value to `i`). After all statements inside the body are executed, the loop returns to the beginning of the body, increments `i := i + stepwidth` and checks the stopping criterion `i > stop`. If `FALSE`, the body is executed again with the new value of `i`. If `TRUE`, the loop is terminated immediately without executing the body again.

- The decrementing loop

  `for i from start downto stop step stepwidth do body end_for`

  implements a corresponding behavior. The only difference is that upon return to the beginning of the body, the loop variable is decremented by `i := i - stepwidth` before the stopping criterion `i < stop` is checked.

- The loop `for x in object do body end_for` iterates `x` over all operands of the object. This loop is equivalent to

                    for i from 1 to nops(object) do
                      x := op(object, i);
                      body
                    end_for

  Typically, `object` may be a list, an expression sequence, or an array. Note that other container objects such as finite sets or tables do not have a natural internal ordering, i.e., care must be taken, if the loop expects a certain ordering of the iterative steps.
- The body of a loop may consist of any number of statements which must be separated either by a colon `:` or a semicolon `;`. The last evaluated result inside the body is printed on the screen as the return value of the loop. Use `print` inside the loop to see intermediate results.
- The loop variable `i`, respectively `x`, may have a value before the loop starts. After the loop is terminated, it has the value that was assigned in the last step of the loop. Typically, in an incrementing or decrementing loop with integer values of `start`, `stop`, and `stepwidth`, this is `i` = `stop` +- `stepwidth`.
- The arguments `start`, `stop`, `stepwidth`, and `object` are evaluated only once at the beginning of the loop and not after every iteration. E.g., if `object` is changed in a step of the loop, `x` still runs through all operands of the original object.
- Loops can be exited prematurely using the `break` statement. Steps of a loop can be skipped using the `next` statement. Cf. example 2.
- The keyword `end_for` may be replaced by the keyword `end`. Cf. example 3.
- Instead of the the imperative loop statements, the equivalent calls of the functions `_for`, `_for_down`, or `_for_in` may be used. Cf. example 4.
- `_for`, `_for_down` and `_for_in` are functions of the system kernel.

#### Example 1

The body of the following loop consists of several statements. The value of the loop variable `i` is overwritten when the loop is entered:

    >> i := 20:
       for i from 1 to 3 do
         a := i;
         b := i^2;
         print(a, b)
       end_for:

                                       1, 1

                                       2, 4

                                       3, 9

The loop variable now has the value that satisfied the stopping criterion `i > 3`:

    >> i

                                         4

The iteration range is not restricted to integers:

    >> for i from 2.2 downto 1 step 0.5 do
         print(i)
       end_for:

                                        2.2

                                        1.7

                                        1.2

The following loop sums up all elements in a list. The return value of the loop is the final sum. It can be assigned to a variable:

    >> s := 0: S := for x in [c, 1, d, 2] do s := s + x end_for

                                     c + d + 3

Note that for sets, the internal ordering is not necessarily the same as printed on the screen:

    >> S := {c, d, 1}

                                     {c, d, 1}

    >> for x in S do print(x) end_for:

                                         1

                                         d

                                         c

    >> delete a, b, i, s, S, x:

#### Example 2

Loops can be exited prematurely using the `break` statement:

    >> for i from 1 to 3 do
         print(i);
         if i = 2 then break end_if
       end_for:

                                         1

                                         2

With the `next` statement, the execution of commands in a step can be skipped. The evaluation continues at the beginning of the body with the incremented value of the loop variable:

    >> a := 0:
       for i from 1 to 3 do
         a := a + 1;
         if i = 2 then next end_if;
         print(i, a)
       end_for:

                                       1, 1

                                       3, 3

    >> delete i, a:

#### Example 3

Loops can be closed with the keyword `end` instead of `end_for`. The parser recognizes the scope of `end` statements automatically.

    >> s:= 0:
       for i from 1 to 3 do
         for j from 1 to 3 do
           s := i + j;
           if i + j > 4 then
             break;
           end
         end
       end

                                         5

    >> delete s, i, j:

#### Example 4

This example demonstrates the correspondence between the functional and the imperative form of `for` loops:

    >> hold(
         _for(i, start, stop, stepwidth, (statement1; statement2))
       )

                    for i from start to stop step stepwidth do
                      statement1;
                      statement2
                    end_for

The optional `step` clause is omitted by specifying the value `NIL` for the step width:

    >> hold(
         _for_down(i, 10, 1, NIL, (x := i^2; x := x - 1))
       )

                             for i from 10 downto 1 do
                               x := i^2;
                               x := x - 1
                             end_for

    >> hold(
         _for_in(x, object, body)
       )

                                for x in object do
                                  body
                                end_for

#### Changes

- `end` can now be used as an alternative to `end_for`.

Do you have questions or comments?
Copyright © SciFace Software GmbH & Co. KG 2000