Sequencing of Units Within a Lesson
We have discussed many units which make different kinds of displays. In some cases, the main units had other units attached to them by means of -do-. Upon completion of a main unit, the student can proceed to the next one by pressing NEXT. A greater variety of inter-unit connections is needed to build a complete lesson which includes optional help sequences, branches to remedial sections when the student is having trouble, an index that gives the student some control over the order of presentation, etc. This section will discuss, in more detail, how to build rich interconnections into a lesson. This discussion builds on the introduction to such matters presented in Chapter 1.
It is often desirable to skip over some units, particularly if they are used as subroutines, not as main presentation units. We have seen that this can be done by using a -next- command to name the main unit which is to follow. For example:
When TUTOR begins “executing” the statements in unit “one”, it starts out assuming that the next physical unit, unit “dispone”, will be the next main unit. However, TUTOR encounters a “next two” statement which says, “No, make a note that unit `two' will be next, rather than the next physical unit”. The “do dispone” is then executed, which involves drawing a figure. Finally, we write “This is unit one”, which is at the end of unit “one”. Nothing more will happen until the student presses the NEXT key, at which time TUTOR looks at its notes and finds that unit “two” comes next, whereupon it erases the screen and starts executing unit “two”. Had we not inserted the -next- command, TUTOR would have gone on to unit “dispone” by default.
To put it another way, TUTOR has a pointer which tells which main unit should come next. At the beginning of a main unit, TUTOR places zero in this pointer to indicate that the next physical unit should be next. If no -next- command is encountered, we reach the end of the unit with the pointer still zero, and when the student presses NEXT, TUTOR will by default proceed to the next physical unit. On the other hand, if we encounter a -next- command anywhere in the unit, it will alter this pointer so that later, when the student presses NEXT, the pointer is non-zero and is pointing to whatever unit we have specified.
It should be clear from this discussion that the -next- command can be executed anywhere in the unit without changing its effect. Nevertheless, it is important to place the -next- command near the beginning of the unit. The advantage is that you can then see at a glance what is the main sequence flow. If the -next- command is buried far down in the unit, you have to hunt for this crucial information. You put such unit information at the beginning of a unit for the same reason that you define appropriate names for the variables you use: you or a colleague may have to read through the lesson months after it was written!
The following is a simple illustration of how the -next- pointer is handled:
Well, what unit will be next? Answer: unit “C”! The pointer starts out cleared to zero (which implies the next physical unit), then gets set to “A”, then to “B”, and finally to “C”. Each succeeding -next- command overwrites what had previously been in the pointer.
It is also possible to clear the next pointer yourself by -next- with no tag or “next q” (“q” for “quit specifying something”). Either of these forms will clear the next pointer so that the next physical unit will come next. In other words, the sequence:
will proceed from unit “start” to unit “again” because the “next q” cancels the “next silly”.
Such seemingly meaningless manipulations are mentioned here for completeness and as aids to explaining how TUTOR handles a unit pointer, such as that associated with the -next- command. These manipulations will make more sense to you later on in the book. The important thing to remember is that you have complete control over the pointer. You can set it or clear it with an appropriate -next- command.
The existence of “next q” (and related statements) means that “unit q” is not a permitted statement (you are not allowed to name a unit “q” because of the possible confusion). For similar reasons you will see later that a unit cannot be named “x”.
Another way to utilize pointers is in specifying optional “help” sequences which the student can request by pressing the HELP key. Such optional sequences are important tools in tailoring the lesson to meet the needs of individual students of diverse backgrounds and abilities. Here is an example. (See Figures 5-2a and 5-2b.)
The -help- command is used to specify a “help” unit, which may be just the first unit in a long help sequence. If you provide help in this way, the student can get it by pressing the HELP key. (Conversely, if there is no -help- command, the HELP key has no effect). When the student enters the help sequence, his or her screen is erased to clear the way for the display generated by the first help unit. The student may at any time press BACK or shift-BACK to return to “home base”, the main unit he or she was in when requesting help. A “base” pointer retains the name of the “base unit” (the unit to return to). In the example, if you press HELP in the base unit “dippy”, TUTOR remembers “dippy” and jumps to “words”, from which the BACK key will take you back to “dippy”. If instead you press NEXT, you advance to “words2”, where you can again press BACK or shift-BACK to return to “dippy”. From “words2” you will also return to “dippy” upon pressing NEXT because the -end- command in unit “words2” signals the end of the help sequence.
It is almost as though the student had two screens to look at! The student starts the lesson in the first unit of a normal, non-help sequence and advances in this sequence until he or she requests help. At this point, the student turns his or her attention to a different, parallel sequence of units, almost as though that student had turned to use another terminal. The student can get back to the original sequence by pressing BACK, as if he or she had turned back to the original terminal. The usefulness of such a parallel sequence is not limited to help sequences but can be used to provide review, a desk calculator mode, a dictionary of terms, tables of data, etc., or for any situation in which the student temporarily needs a second terminal “off to the side”.
It is possible to access yet another help sequence when you are already in a help sequence. BACK, however, will return you to the original base unit, not the help unit you were in when you requested the second help sequence. This is due to the fact that there is only one base pointer, which is not changed by the second help request. If there is already a base unit specification, TUTOR does not alter it.
You can alter fhe base unit pointer yourself with a -base- command. If you put a -base- command with no tag in unit “words” you will prevent a return to “dipper” or “dippy”. The -base- command with no tag or a “base q” statement clears the base pointer so that TUTOR forgets where to return to and thinks that you are not in a help sequence. (You should notice that the -end- command in unit “words2” is now ignored. The -end- command has no effect in a non-help sequence.) This -base- (blank or “q” tag) is used quite often since it is frequently convenient to put the student into a non-help sequence, even though he reached a certain point by pressing HELP. Also, TUTOR automatically clears the base pointer whenever and by whatever means the student reaches the corresponding base unit. You can change the base pointer to point to some unit other than the original one. Imagine that we place the following statement in unit “words”:
This means TUTOR will eventually return to “dispone” rather than “dipper” or “dippy”. This is occasionally a useful technique. For example, you might like to return to a unit just ahead of the original one in order to ease back into the original context. Notice, too, that while -base- with no tag (or “q”) can change a help sequence into a non-help sequence, so “base unitname” can change a non-help sequence into a help sequence by naming a unit to return to.
You probably will not need all of the features of -help-, -base-, and -end- described_above, but hopefully the discussion has clarified how they do their work. You have also discovered some terms which will be quite useful in later discussions and can now talk about “non-help sequences” of “main units” and “help sequences” of “main units”. It should be pointed out that a base unit may have other (auxiliary) units attached to it by -do-; and, of course, you return to the base unit itself, not to one of these attached units, even if the -help- command is located in an attached unit. Moreover, a lesson may be thought of as a collection of main units which have attached units, and the student moves from one main unit to another. The student may enter a help sequence of main units, each of which may -do- attached units. While the student is in the help sequence, TUTOR remembers which main unit is the “base” unit to return to when -end- is encountered, or when BACK or shift-BACK is pressed. The following is a diagram of this structure:
You may have realized that -help- and -base- are quite similar to -next- in that all three commands set pointers. (The pointers have different uses, however). For example, if we say:
then the last one wins - the help pointer ends up pointing at unit “c”. We saw earlier that -next- works this way. Similarly, “help q” or -help- with no tag will clear the help pointer, thus making the HELP key inoperative.
You may find it helpful to think of a help sequence as a “slow” subroutine. Whereas a -do- command takes us to a unit and right hack again, -help- makes possible an optional jump to a unit or to a sequence of units where the student may study for many minutes before returning to the base unit. Aside from the “slowness” and the necessity of pressing keys to go and return, there is one fundamental difference from a -dosituation. In a help sequence, we return from help to the beginning of the base unit and re-execute the statements in the unit in order to restore the original display, whereas the return from a -do- is to the statement following the -do-.
This last point is sufficiently important to warrant an example:
(Of course, “a” must be defined.) If we repeatedly press HELP, then BACK, while we are in unit “repeat” we will repeatedly increment variable “a”. Variable “a” increases by one on every return from the help sequence because the return is to the beginning of the base unit, and all the statements in unit “repeat” are re-executed. This is necessary to restore (to the screen) the display associated with unit “repeat”, since the entire screen is erased when the HELP and BACK keys are pressed.
This example brings up a fundamental programming point: the
question of initialization. We might use a structure like that shown above
for counting the number of times the student presses the HELP key
(although we would then most likely put the a⇐a+1
in the help unit).
In order to count something (requests for help, number of wrong
answers, etc.), it is necessary to “initialize” the counting variable to zero
before starting the process, and this initialization must precede (and be
outside) the process itself. This can perhaps best be seen by moving the
statement calc a⇐0
from unit “initial” to the beginning of unit
“repeat”:
Imagine pressing HELP (and BACK) repeatedly. There would never be a change in the displayed value of “a”, because on each return from the help unit, “a” is again reset to zero (whereas that was previously done only within unit “initial”).
The question of initialization will be encountered again and again in various guises. These matters were not mentioned earlier partly because the iterative -do- command had the initialization built-in. For example:
It should be mentioned here that initialization questions are, of course, not unique to programming. The principal and interest due monthly on your car or house loan depend on the initial conditions of the loan. When you make fudge, you start with certain ingredients in the mixing bowl (the initial condition) and then you beat the mixture 200 times. You would no more restart with new, unmixed ingredients after each beating stroke than you would reinitialize a count of student errors after each attempt. In other words, questions of initialization are mainly questions of common sense, and we will make explicit comments about these matters only where confusion is likely. In the case of a return from a help sequence, you might have thought that TUTOR remembers the entire display originally made by the base unit. However, as you have seen, TUTOR must re-create the display by re-executing the commands in the base unit (which has side effects related to initialization questions).
Now, let's move the “calc a4” back to unit “initial” and modify the unit to look like this:
The -jump- command acts much like the student pressing NEXT (the screen is erased and we move to a new main unit). The -jump- command is particularly useful in association with initializations, as in this example, where it is necessary to separate initializations from a process in a different unit. It would be superfluous to show the student a blank screen and to make the student press NEXT. Indeed, it should be a basic rule to minimize unnecessary keypresses so as not to frustrate the student. Notice that -jump- is immediate (like -do- and unlike the -next- or -helpcommands) and that statements which follow -jump- in a unit will not be executed (unlike -do-, -next-, and -help-).
The base pointer is not affected by a -jump-. The pointer remains zero if we are not in a help sequence, and it retains its base unit specification if we are in a help sequence. The -jump- simply takes us from one new main unit to another without having to press NEXT. Since it starts a new main unit, a -jump- cancels any -do-s which have been encountered (there will be no return from those -do-s).
When moving from one main unit to another, by -jump- or by pressing NEXT, the entire screen is erased unless the first of these two main units contains an “inhibit erase” statement. For example, the sequence:
will leave the old display on the screen, and displays created by unit “more” will be added to the screen.
Since -jump- takes the student from one main unit to another without altering the base pointer, it is possible to take a student to a help sequence immediately without pressing FIELP:
Initially, the base pointer is zero because we are in a non-help sequence. Then, a -base- command is used to set the base pointer to unit “model” (the main unit we are presently in). The -jump- takes us to unit “modhelp”.
Now we are in a help sequence because the base pointer has been set. The return from the help sequence will be to the beginning of unit “model”. Note the difference between “base model” and “base q” in unit “model”: a “base q” statement would clear the already-cleared base pointer, whereas “base model” sets the pointer to “model”.