
DO loops go round a known number of times. Often you do not know the number. You want to go on until the number gets small enough, or until somebody presses a key. SuperForth has two loops for that, and they differ only in where they ask the question.
: COUNTDOWN BEGIN DUP . 1 -
DUP 0= UNTIL DROP ;
Everything between BEGIN and UNTIL is repeated. Each time round, UNTIL takes a flag from the stack. If the flag is false it goes back to BEGIN; if it is true it carries on. "Do this until that is true."
Follow 5 COUNTDOWN. Print a copy of the number; take one off; ask whether a copy of it is zero. While it is not, go round again. When it is, UNTIL lets go, and the DROP clears away the zero that is left.
Because the question comes at the end, the body always runs at least once.
: DOUBLING 1 BEGIN DUP 100 <
WHILE DUP . 2 * REPEAT DROP ;
Here the question is in the middle. WHILE takes a flag: if it is true, carry on through to REPEAT, which goes back to BEGIN; if it is false, jump out past REPEAT. "While this is true, do that."
Two differences from UNTIL. The sense is the other way up: WHILE goes on when the flag is true. And since the test comes before the work, the work may not happen at all.
: COUNTDOWN BEGIN DUP . 1 -
DUP 0= UNTIL DROP ;
5 COUNTDOWN
: DOUBLING 1 BEGIN DUP 100 <
WHILE DUP . 2 * REPEAT DROP ;
DOUBLING
Starting from
A fresh boot, with SuperForth just started.
What you should see
5 COUNTDOWN
5 4 3 2 1 ok
DOUBLING
1 2 4 8 16 32 64 ok

Two words bring the keyboard into it.
KEY stops and waits for a key to be pressed, and leaves that key's code on the stack. KEY . and then pressing A prints 65. If you only want the pause and not the code, KEY DROP.
?TERMINAL does not wait. It leaves a flag there and then: true if a key is being pressed right now, false if not. Which makes it the natural partner of UNTIL:
: SPIN BEGIN 42 EMIT ?TERMINAL UNTIL ;
prints stars until you touch a key.
One thing to know: ?TERMINAL notices the key but does not take it. The key is still waiting afterwards, and will turn up at the front of the next thing that reads the keyboard. KEY DROP straight after the loop takes it away.
Both of these loops will run for ever if their condition never comes. A COUNTDOWN given 0 starts by going to -1, and then has a very long way to go to reach zero again.
Before you press ENTER on a word with a BEGIN in it, ask what makes it stop, and whether that is certain to happen. When you are not sure, put ?TERMINAL into the condition with an OR, so that a key will always get you out.
COUNTDOWN so that it prints down to 0 instead of stopping at 1.DOUBLING, change 100 < to 1 <. What is printed, and what does that tell you about when WHILE asks its question?: ONCE BEGIN ." HELLO " 1 UNTIL ; How many times does it print, and why can it never be none?KEY . and press a few different keys, one run each. What is the code for the space bar? For ENTER?15.1 Define HALVING ( n -- ) to print a number, then half of it, then half of that, until it reaches zero. Try it on 100.
15.2 Define THREES to print the powers of three below 1000, using WHILE.
15.3 Define PAUSE to print PRESS ANY KEY, wait for one, and then print THANKS.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| The loop never ends | Its condition never came true. Restart the Einstein - nothing you had saved is lost - and then work out what should have stopped it. |
| It stops after one pass | The flag is already true the first time UNTIL sees it. UNTIL stops on true; you may have the test the wrong way round. |
A WHILE loop does nothing | Its test was false the first time. Unlike UNTIL, that is allowed. |
| A number left behind on the stack | The test used a DUP and nothing dropped the last copy. Both listings end with DROP for that reason. |
BEGIN ... flag UNTIL repeats until the flag is true and always runs once. BEGIN ... flag WHILE ... REPEAT repeats while the flag is true and may not run at all. KEY waits for a key and leaves its code; ?TERMINAL reports a key without waiting. Every loop needs a certain way out.
S16, One Of Several - choosing among many possibilities without a ladder of IFs.