This type of loop is known as a definite loop. It will loop a specific number of times and then continue with the program. If you wanted to count to ten you could setup the following:
ok 10 0 do i 1+ . cr loop
1
2
3
4
5
6
7
8
9
10
The two numbers before do are the limit and the index of the
loop. The index is the number to start incrementing from, in this
case zero, and the limit is the number of times the loop will repeat
itself, in this case ten. Why 0...10? Because each iteration of the
loop causes a test to be performed: Is i less than the limit?. Within
a do...loop, i represents the current loop index. So we are
checking to see if i<10 in the above example after every every
carriage return (cr). If we had wanted the obvious 1..10
loop, the test would have to be i<=10, which requires two
additional tests (one to check if i is less than ten and one
to check if i is equal to ten). Plus, programmers tend to
count to ten by starting at zero and going to nine because array
indices start at zero. The "." (dot) is a word which pops a number off of the stack and displays it on the screen (more about this and other types of output in 7. Strings, Fields And Output).
do ... loop do: ( limit index -- ) loop: ( -- ) Set up a finite loop, given the index range.
do ... +loop do: ( limit index -- ) +loop: ( n -- ) Set up a finite loop similar to a DO...LOOP except that the index will increase by n instead of one.
leave ( -- ) causes the DO...LOOP to end at the next loop or +loop.
ok 0 begin 1+ dup . cr dup 10 = until
1
2
3
4
5
6
7
8
9
10
Not very pretty, but it works. This shows why you would use a
DO...LOOP instead of a BEGIN...UNTIL. Now how about the reverse?
A good example of when to use a BEGIN...UNTIL loop is when a condition
changes all of sudden, such as waiting for a DSP card to finish
processing:
: init.board ( -- ) \ Run DSP program to intialize board.
initializeboard \ Load SPECTRUM's initialization code onto board
h# 100 runprog \ Start NIR setup subprogram running on dsp 56001 board
begin
readdspflag 0= \ Wait until dsp program lowers its "run" flag
until ;
While the program is running on a DSP card, readdspflag will
poll the DSP card, checking to see if the program is still running and
will return true if it is. 0= determines whether the flag is
equal to zero. So if the program has finished, 0= will
return true and the loop will end. begin ... until until: ( f -- ) Set up an indefinte loop, repeating until f is true.
An example of using a BEGIN xxx WHILE yyy REPEAT loop is to query the user for a number between 0 and 9, maybe as part of a menu selection process.
: get-menu-item ( -- n ) \ Query user for a menu option.
begin
." Enter the menu item you desire: "
key dup emit cr ascii 0 - dup 0 9 between not
while
drop
." Not a valid menu number! Try again." cr cr
repeat ;
begin xxx while yyy repeat while: (
f -- ) Set up an indefinite loop which always executes xxx and
executes yyy if f is true. The loop ends when f is false. Note that
this loop reacts differently to the flag than BEGIN...UNTIL.