prev | toc | next
 

3.2 Overview: MUF (cont'd)

Loops:

A loop is a section of code that executes repeatedly, until a certain condition is met. The programmer defines the condition. If no condition is defined (or if the condition is one that will never be met), the loop will continue to execute indefinitely. This is called an `infinite loop'. The code for a loop begins with the primitive BEGIN and ends with either REPEAT or UNTIL.

A common way to define the exit condition of a loop is to use a variable to store the number of times the loop is to execute. With each repetition (or `iteration') of the loop, the variable is increased (`incremented') or decreased (`decremented') by one. When the value stored in the variable matches a predefined limit (often 0), the loop exits. The following version of tinker.muf uses a loop controlled in this manner to do the `random number test' from the previous version three times.

====================================
lvar ourNumber
lvar ourCounter

: TellTrue

    me @ "Yes, the number is greater than one million." notify
;

: TellFalse

    me @ "No, the number is less than one million." notify
;

: main

    3 ourCounter !

    begin

        ourCounter @ 0 = if
            break
        then

        random ourNumber !

        ourNumber @ 1000000 > if
            TellTrue
        else
            TellFalse
        then

        me @ ourNumber @ intostr notify

        ourCounter @ 1 - ourCounter !

    repeat

    me @ "OK, we're done with the loop." notify
;
====================================

At the very top of the program, we declared the local variable ourCounter. In the first line in main, we stored the integer 3 in our variable ourCounter. The next line is BEGIN, which starts the loop. The first thing MUF does with each pass through the loop is check to see if the value stored in ourCounter is 0. If it is, execution BREAKs out of the loop, and does whatever comes next (which in this case is to tell us "OK, we're done.")

In the first iteration of the loop, the IF test will be false, because we just put a 3 in ourCounter, not a 0. So the loop will continue, executing our random number test. Then, at the bottom of the loop, we fetch the number out of ourCounter, subtract 1 from it, and then store the new number back in ourCounter. Then the loop REPEATs, jumping back to the top of the loop. This time, the value in ourCounter is 2... still not 0, so the loop exectutes again. The next time the loop repeats, the value is 1: the random number test has executed three times. Then execution will jump back to the top of the loop and begin for a fourth iteration. This time, however, the value stored in ourCounter has reached 0. The IF test will be true, so the BREAK will be executed. The program jumps out of the loop and does whatever comes after the REPEAT (tells us we're done).

Here we are using IF to see if it is time to break out of the loop. MUF provides another conditional statement that does the same thing in shortened form. WHILE tests the top value on the stack for truth, just like IF does. When an IF test is true, code between the IF and its matching THEN is executed; otherwise, it skips to whatever follows the THEN. When a WHILE test is true, code between the WHILE and the next REPEAT or UNTIL is executed; otherwise, it skips to whatever follows the REPEAT or UNTIL. In other words, the loop continues to execute WHILE the condition is true.

In the above version of tinker.muf, we used...

    ourCounter @ 0 = if
        break
    then

to exit the loop. We could accomplish the same thing with...

    ourCounter @ while

As long as ourCounter is not 0, it will be true, and the rest of the loop will execute. When it gets to 0, it becomes false, and the WHILE will cause execution to break out of the loop.

UNTIL also provides a way to exit from a loop. The UNTIL marks the `bottom' of the loop, like a REPEAT, but also serves as an exit-condition check like WHILE. If the value on top of the stack is true when the program gets to UNTIL, execution `falls through' the bottom of the loop and continues from there. For example, the following loop repeats until RANDOM generates an integer greater than 1.5 billion.

====================================
    begin
        random
        dup intostr me @ swap notify
        1500000000 >
    until
====================================

With each iteration, the loop generates a random number, converts it into a string and notifies the user, then tests to see if it's greater than 1.5 billion. If so, the top value on the stack at UNTIL will be true, and the program will exit the loop. Otherwise, execution jumps back to BEGIN, and the loop repeats.

prev | toc | top | next