Node:Counted Loops, Next:Arbitrary control structures, Previous:Simple Loops, Up:Control Structures
The basic counted loop is:
limit start ?DO body LOOP
This performs one iteration for every integer, starting from start
and up to, but excluding limit. The counter, or index, can be
i. For example, the loop:
10 0 ?DO i . LOOP
0 1 2 3 4 5 6 7 8 9
The index of the innermost loop can be accessed with
i, the index
of the next loop with
j, and the index of the third loop with
iR:n -- R:n n core ``i''
jR:n R:d1 -- n R:n R:d1 core ``j''
kR:n R:d1 R:d2 -- n R:n R:d1 R:d2 gforth ``k''
The loop control data are kept on the return stack, so there are some restrictions on mixing return stack accesses and counted loop words. In particuler, if you put values on the return stack outside the loop, you cannot read them inside the loop1. If you put values on the return stack within a loop, you have to remove them before the end of the loop and before accessing the index of the loop.
There are several variations on the counted loop:
LEAVEleaves the innermost counted loop immediately; execution continues after the associated
NEXT. For example:
10 0 ?DO i DUP . 3 = IF LEAVE THEN LOOPprints
0 1 2 3
UNLOOPprepares for an abnormal loop exit, e.g., via
UNLOOPremoves the loop control parameters from the return stack so
EXITcan get to its return address. For example:
: demo 10 0 ?DO i DUP . 3 = IF UNLOOP EXIT THEN LOOP ." Done" ;prints
0 1 2 3
?DOloop is entered (and
LOOPiterates until they become equal by wrap-around arithmetic). This behaviour is usually not what you want. Therefore, Gforth offers
U+DO(as replacements for
?DO), which do not enter the loop if start is greater than limit;
+DOis for signed loop parameters,
U+DOfor unsigned loop parameters.
?DOcan be replaced by
DOalways enters the loop, independent of the loop parameters. Do not use
DO, even if you know that the loop is entered in any case. Such knowledge tends to become invalid during maintenance of a program, and then the
DOwill make trouble.
LOOPcan be replaced with
n +LOOP; this updates the index by n instead of by 1. The loop is terminated when the border between limit-1 and limit is crossed. E.g.:
4 0 +DO i . 2 +LOOP
4 1 +DO i . 2 +LOOP
n +LOOPis peculiar when n is negative:
-1 0 ?DO i . -1 +LOOP
0 0 ?DO i . -1 +LOOPprints nothing.
Therefore we recommend avoiding
n +LOOP with negative
n. One alternative is
u -LOOP, which reduces the
index by u each iteration. The loop is terminated when the border
between limit+1 and limit is crossed. Gforth also provides
U-DO for down-counting loops. E.g.:
-2 0 -DO i . 1 -LOOP
-1 0 -DO i . 1 -LOOP
0 0 -DO i . 1 -LOOP
-LOOP are not defined in ANS Forth. However, an implementation
for these words that uses only standard words is provided in
Another counted loop is:
n FOR body NEXTThis is the preferred loop of native code compiler writers who are too lazy to optimize
?DOloops properly. This loop structure is not defined in ANS Forth. In Gforth, this loop iterates n+1 times;
iproduces values starting with n and ending with 0. Other Forth systems may behave differently, even if they support
FORloops. To avoid problems, don't use
well, not in a way that is portable.