Go to the first, previous, next, last section, table of contents.


Fun With if

Most programming languages offer two basic ways of altering the normal left-to-right, top-to-bottom code execution sequence: a way of looping repeatedly over a section of code, and a way of executing a section of code only if some condition is true.

We've seen a way to execute code repeatedly, using for; Let's look at a way to execute code conditionally, using if:

Stack:
: flip   frandom 0.5 >  if "heads!\n" else "tails!\n" fi  ,  ;
Stack: 
flip
tails!
Stack: 
flip
tails!
Stack: 
flip
heads!
Stack: 
flip
tails!
Stack: 
flip
heads!
Stack:

How does this work? Well, it introduces several new functions. One is frandom, a function which returns a randomly selected number between 0.0 and 1.0:

Stack:
frandom frandom frandom frandom
Stack: 0.00176691 0.187589 0.990434 0.750497
pop pop pop pop frandom frandom frandom frandom
Stack: 0.366273 0.351209 0.573344 0.132554
pop pop pop pop frandom frandom frandom frandom
Stack: 0.0641664 0.950853 0.15356 0.584649

Another is >, a function which returns a true value if its first argument is greater than the second, else a false value. What is a false value in MUF? The special constant nil. What is a true value in MUF? Any but nil!

Stack:
1 2 >
Stack: nil
pop  2 1 >
Stack: t

You can compare strings as well as numbers with >:

Stack:
"alpha" "beta" >
Stack: nil
pop  "beta" "alpha" >
Stack: t

And, as you might expect, MUF has the full usual set of comparison functions:

!=        Not-equal
<         Less-than
<=        Less-than-or-equal-to
=         Equal-to
>         Greater-than
>=        Greater-than-or-equal-to

Notice that it looks a little odd to write "1 2 >" instead of "1 > 2" the way Ms Grundy did in third grade, but that this order is required by our strict rule of evaluating words left-to-right: > cannot execute until we have pushed both of its operands on the stack for it.

(We could make special exceptions from left-to-right evaluation order just for comparison functions, but then MUF would start getting more complicated than we want, and become a quite different sort of language. There is nothing wrong with building more complicated languages designed to look more like what Ms Grundy taught in school, and Muq will eventually have such languages as well as MUF, but for now let's stick to our simple-minded little language.)

With that background in mind, let's take another look at our flip function:

: flip   random 0.5 >  if "heads!\n" else "tails!\n" fi  ,  ;

The "random 0.5 >" will leave a true value on the stack half the time, and a false value (nil) on the stack the other half of the time. What does the if do?

In MUF, if pops one value off the stack and looks at it. If that value is true (anything but nil), all the words from if to else are executed. If that value is false (nil), all the words from else to fi are executed. (fi, as you might guess, is just if backwards, and serves to mark the end of the statement.)

In function flip, this means that the if-else-fi pops a true/false value off the stack, and then pushes either "heads!\n" or "tails!\n" on the stack, to get printed by the final comma function.

Again, it looks peculiar to put the true/false value controlling the if before the if, but that order is forced by our simple-minded left-to-right evaluation rule: if cannot make its decision until we give it the information it needs.

You may wish to experiment interactively with if for awhile, until it begins to feel natural:

Stack:
nil     if "Yup!" else "Nope!" fi
Stack: "Nope!"
pop   t if "Yup!" else "Nope!" fi
Stack: "Yup!"
pop 2.3 if "Yup!" else "Nope!" fi
Stack: "Yup!"

Believe it or not, you've now mastered most of the essentials of elementary MUF programming! In principle, you now know enough MUF to compute anything which can be computed.

Let's finish off by covering a few very handy and frequently used facilities.


Go to the first, previous, next, last section, table of contents.