Essential Elements of Modula 3

Repetition

The final sort of activity that we need to illustrate is that of repetition. There are three different ways of doing this in Modula 3, using a while-loop, a repeat-loop, and a for-loop. The first two provide opportunities for unbounded repetition, whereas the third is for bounded repetition. For the moment I wish to restrict my description to unbounded repetition using the while-loop, because this is the most useful and general of the three.

Let us look back at the example in which we flavoured the soup:


Flavour the soup:
    Taste the soup.
    While there isn't enough salt in it,
        Add another pinch.
        Taste the soup.

We can turn this into a form of Modula 3 as follows:


TasteTheSoup;
WHILE TheSoupNeedsMoreSalt DO
    AddAnotherPinchOfSalt;
    TasteTheSoup;
END;

A while-loop has a Boolean expression between the WHILE and the DO, and set of actions to be performed each time around the loop. The Boolean expression is a condition just as we saw with the if-statement. When the loop is reached, this expression is evaluated and one of two things will happen depending on the value of the expression:


TasteTheSoup;
WHILE TheSoupNeedsMoreSalt DO
    AddASpoonfulOfSugar;
    TasteTheSoup;
END;

The condition only tests the saltiness of the soup. When we enter the body of the loop we do nothing to change its saltiness, only its sweetness. Having decided the first time the test was made that the soup isn't salty enough, no amount of adding sugar will make it any saltier. A human taster would soon detect that something was wrong and take corrective action. A computer obeying these instructions is unable to do anything other than what is written there, and the loop will never end. This might seem like a daft example, but it serves to illustrate the important principle of infinite repetition - resulting in a program that never stops.

Can you write a while-loop that keeps on adding one number, Num, to another, Sum, until Sum is larger than 100?

In general a piece of program in which a while-loop is incorporated will have the following sort of structure:


Do something that will enable us to
 test the initial value of the condition;
WHILE the condition is true DO
   Do something has to be repeated
		 several times;
   Do something that will affect the
		 loop's condition;
END;

Quite often, the action that `will affect the loop's condition' will be identical with the action that enables us `to test the initial value of the condition.' Alternatively, it may be that the action `that has to be repeated' will, itself, have an effect on the condition; nevertheless this gives a good general rule of thumb for what while-loops will look like. Here is a practical example whose task is to read a list of numbers and print the sum of them:


(*
 *  Program's Purpose: To print the sum of numbers typed by
 *                     the user.
 *  Author: David Barnes, April 1996.
 *)
MODULE AddUpSomeNumbers EXPORTS Main;
IMPORT Get, Put;
    (* Define the procedure in which the overall task
     * is performed.  The task is to read in some positive
     * numbers from the user and add them up.  Each number
     * is to be typed on its own line.
     * The user indicates the end of the list by typing a
     * negative number, which is not to be included in the sum.
     *)
PROCEDURE PrintASum() =
VAR
    (* Define a variable to hold each number typed by the user. *)
    NextNumber : REAL;
    (* Define a variable to keep the total read so far. *)
    Total : REAL;
BEGIN
    (* Make sure that our total starts at zero. *)
    Total := 0.0;
    (* Read the first number.  It could be negative. *)
    Get.Real(NextNumber);
    (* Keep going until we read a negative number. *)
    WHILE NextNumber >= 0.0 DO
        Total := Total + NextNumber;
        Get.Real(NextNumber);
    END;
    Put.Text("The total is:");
    Put.Real(Total);
    Put.Char('\n');
END PrintASum;
BEGIN
    PrintASum();
END AddUpSomeNumbers.

Stepping through the example we see the following points:


{ Read the first number.  It could be negative. }
Get.Real(NextNumber);

This corresponds to the first aspect of our pattern:


Do something that will enable us to test the initial value
                   of the condition;

It also has the useful effect of ensuring that we will cope quite easily with the situation where the first number typed by the user is negative - indicating the end of a list with no positive values in it.


Total := Total + NextNumber;

This corresponds to:


Do something to be repeated several times;


Do something that will affect the loop's condition

Clearly, we have done all we need to with the current value so we:


Get.Real(NextNumber)

so that, when we return to check the loop's governing condition, we shall be testing a different value from the last time around.

To
Previous Page

To Overview

To Next Page