
S13 gave you questions. This section gives you something to do with the answers.
: SIZE 100 > IF ." BIG"
ELSE ." SMALL" THEN ;
IF takes a flag from the stack. If the flag is true, the words between IF and ELSE run. If it is false, the words between ELSE and THEN run instead. Either way, things carry on after THEN.
The order takes getting used to, because it is Forth's order: the question comes first, already answered and sitting on the stack, and IF only acts on it. Read THEN as "and then carry on". It marks the end of the choice, not the start of a consequence.
If THEN jars too much, SuperForth lets you write ENDIF instead. It does the same job.
Like loops, IF only works inside a definition.
: SIZE 100 > IF ." BIG"
ELSE ." SMALL" THEN ;
500 SIZE
7 SIZE
Starting from
A fresh boot, with SuperForth just started.
What you should see
500 SIZE
BIGok
7 SIZE
SMALLok

Often there is nothing to do when the answer is no. Leave the ELSE out:
: MYABS DUP 0< IF MINUS THEN ;
If the number is negative, change its sign; otherwise leave it alone. The DUP is essential, and it is the mistake everyone makes once: 0< uses up the number it tests, and IF uses up the flag. Without the DUP there would be nothing left to take the sign of.
IF does not insist on a 1. Anything that is not zero counts as true. That is what -DUP from S6 is for. It copies the top number only when it is not zero, so
: SHOW -DUP IF . THEN ;
prints a number unless it is zero, and leaves the stack clean in both cases: with a non-zero number there is a copy for IF to use up and the original for .; with zero there is only the zero, and IF uses that up.
: GRADE DUP 70 > IF ." MERIT" ELSE
DUP 50 > IF ." PASS" ELSE ." FAIL"
THEN THEN DROP ;
Each IF needs its own THEN, which is why there are two at the end. It works, and you can see it is already getting hard to read. Two deep is about the limit; S16 has a better tool for choosing among several things.
S12 left a problem: a loop always runs once, so 0 STARS prints a star. Now you can stop it:
: STARS -DUP IF 0 DO 42 EMIT
LOOP THEN ;
It is split over two lines because on one it would be exactly 40 characters long, and S7 explained what becomes of those. With 0 on the stack, -DUP leaves just the 0, IF takes it as false, and the loop is skipped.
SIZE so that exactly 100 counts as big. There is more than one way.ELSE ." SMALL" out of SIZE. What does 7 SIZE print now?DUP from MYABS and try -9 MYABS . What went wrong, and where did the 9 go?STARS and try 0 STARS, 1 STARS and 5 STARS.14.1 Define EVEN-ODD to print EVEN or ODD for the number on the stack.
14.2 Define BIGGER ( n1 n2 -- n ) to leave the larger of two numbers, without using MAX.
14.3 Define COUNT-UP ( n -- ) to print the numbers from 1 to n, and to print nothing at all if n is 0.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
IF? Compilation only, Use in Definition | IF typed at the keyboard. It has to be inside a word. |
Empty Stack, or a wrong answer, after an IF | The test used up the number you wanted afterwards. DUP before testing. |
| A number left on the stack that should not be | One branch used the number and the other did not. Both branches must leave the stack the same. |
;? Definition not Finished | An IF without its THEN. Count them. |
Isn't Unique for a name you thought was new | SuperForth already has it. SIGN and END are both taken. |
flag IF ... ELSE ... THEN runs one set of words or the other; ELSE is optional and ENDIF is another name for THEN. IF uses up the flag, any non-zero number counts as true, and the test usually needs a DUP in front of it. Both branches should leave the stack the same way.
S15, Until It's Done - loops that go round not a set number of times but until something happens.