Into the ARC

This month Mike Williams looks at the provision for looping and branching in Basic V.

Readers of RISC User may recall that in the first article in this series (Volume 2 Issue 7) I presented an overview of the whole process of writing a program. That process, to be successful, depends upon creating a clear structure for your program. In turn this means making frequent use of functions and procedures, the subject of last month's article. It also requires a good understanding of the branching and looping constructs provided on the Archimedes by Basic V.

The idea that a program can be written so that a certain section of code is repeated (a loop), or that a program can be made to choose between two or more different routes through the program (branching) is fundamental to the whole concept of programming (and indeed was first formalised by one of the founders of modern computing, von Neuman, in 1947).

LOOPS

The simplest form of loop can be set up using a GOTO statement to refer to a previous line in a program, but as I have said before, GOTOs do not lead to clear programs, and on the whole are to be avoided when possible. For example, it is only when you reach such a GOTO in a program that you realise that the preceding coding forms part of a loop anyway, as there is nothing which explicitly indicates where the loop begins.

Basic, on all computers, provides an obvious looping mechanism in the form of the FOR-NEXT statement, which is ideal when we want to repeat a group of instructions a 'known' number of times. This uses any variable of our choice to count the number of times the instructions are to be repeated. In its simplest form we might, as an example, write:
FOR m = 1 TO month
READ month$
NEXT mDATA January, February, March . . .

where the value of month determines one of the months in the year whose name we wish to read from a set of DATA statements. The variable m simply counts from 1 (the starting value) up to the value of month. A FOR-NEXT loop always begins with the keyword FOR and terminates with the keyword NEXT, so it is always easy to recognise such a loop in any program, and you will find many examples to study in the programs listed in RISC User.

By default, FOR-NEXT loops always count upwards in steps of 1, but you can count both up and down in whatever step size you wish by specifying this with the keyword STEP. For example:
FOR x = 40 TO 1240 STEP 100
LINE x,0,x,1024
NEXT x

would draw a series of vertical lines (in the current graphics colour) at intervals of 100 graphics units across the screen.

A few comments at this stage may not go amiss. If the loop counts upwards the starting value should be smaller than (or equal to) the final value; for counting downwards the reverse should be true. Loops can be nested one within another, but must not overlap. And never put the NEXT into any form of conditional statement (IF-THEN-ELSE) - even if you get it to work it is bad practice, and any later changes can cause no end of trouble.

There is also a particular problem with the implementation in BBC Basic (though this does not necessarily apply in all versions of Basic). Consider the following example:
100 PRINT"Times to toss a coin";
110 INPUT n
120 heads=0:tails=0
130 FOR toss=1 TO n
140 value=RND(2)
150 IF value=1THEN heads=heads+1 ELSE tails=tails+1
160 NEXT toss
170 PRINT¦Heads ";heads;" tails ";tails
180 END

This is designed to count the number of times heads or tails will appear in tossing a coin. Lines 140/150 will randomly assign either 1 or 2 to value each time the loop is repeated.

Now logically, we would expect that if the answer to the initial question (and hence the value of n) happened to be given as 0, then the loop would not be executed at all. In fact, it will still be executed once, giving an incorrect result. A FOR-NEXT loop will always be executed at least once, even if the starting and terminating values suggest that this is wrong. This is something you need to be aware of whenever you use the FOR-NEXT construction.

However, Basic V provides two further ways of controlling loops which behave more logically. These alternatives also control loops in a fundamentally different way. FOR-NEXT should be used only when the number of repetitions is known at the start of execution of the loop. The alternative is to repeat a section of the program until some condition is satisfied. For example, we may wish to search (or read) through a list of names until a particular name is found. We don't know where in the list the required name might be so we cannot count through the names to find it.

The two alternatives (in BBC Basic) are REPEAT-UNTIL and WHILE-ENDWHILE. The former will repeat a group of instructions until some condition is satisfied, but note the order - perform the task until complete. Many programs consist of a main loop which is repeated until the user decides to exit from the program, and this is often expressed as a REPEAT-UNTIL loop:
exit%=FALSE
REPEAT
PROCdisplay_menu
option%=FNselect_option
PROCexecute(option%)
UNTIL exit%

This outline program uses a variable exit% to act as a flag in the program. Initially the flag is set to be FALSE. The main loop is presumed to display a menu on the screen from which the user makes a choice, and the program then performs the selected task. It assumes that one of the menu choices is an exit from the program which if selected causes exit% to be set to TRUE. When this happens the program exits from the REPEAT-UNTIL loop because the terminating condition has been satisfied. Again, you will find many of the programs which we publish contain examples of this structure, presented in outline above (using procedure calls).

There are many situations in most programs where a REPEAT-UNTIL form of loop is the natural choice, whether as a major feature, or as minor component. Here is a simple example of a REPEAT-UNTIL loop which is used quite commonly in many programs:
REPEAT
G$=CHR$(GET AND &DF)
UNTIL G$="Y" OR G$="N"

The loop is repeated until either 'Y' or 'N' is pressed (GET AND &DF converts any lower case letters to upper case before testing). This can be extended into a useful little function:
1000 DEF FNask(text$)
1010 LOCAL G$
1020 PRINT text$+"?";
1030 REPEAT
1040 G$=CHR$(GET AND &DF)
1050 UNTIL G$="Y" OR G$="N"
1060 =(G$="Y")

This will display any message supplied as the parameter of the function, and return the value TRUE if the answer is 'Y' (for yes) or FALSE if 'N' (for no). For example, you might put in a game:
100 PROCstart
110 REPEAT
120 PROCplay_game
130UNTILFNask("Finish game")
140 END

However, note that the terminating condition is only tested after the body of the loop has been performed at least once. Thus a REPEAT-UNTIL loop suffers the same restriction in this respect as does a FOR-NEXT loop.

This is not so with the other form of conditional loop, the WHILE-ENDWHILE construction. Because this form of loop is less well known, it is worth defining its syntax a little more carefully than we have done hitherto. It takes the form:
WHILE <condition>
<statement(s)>
ENDWHILE

As long as the specified condition remains true, the body of the loop will continue to be executed. If the condition is not satisfied at all, the following action will never take place.For example, we might write:
xpos=640:ypos=512
WHILE (xpos>x1 AND xpos<x2) AND (ypos>y1 AND ypos<y2)
PROCmove(xpos,ypos)
MOUSE xpos,ypos,state
ENDWHILE

This will allow the mouse to move a pointer on the screen for as long as the pointer position remains between the bounds set by x1 and x2, and y1 and y2.

A good programmer will be conversant with all the methods in Basic by which a loop may be constructed, and be able to select the one which is most appropriate (most natural) in any given instance.

BRANCHING

The same should also be true when it comes to branching, at its simplest in the form of the IF-THEN statement. Again, this is a standard feature of all Basics, but if you are new to BBC Basic, then you need to familiarise yourself with its precise syntax in more complex examples. First of all, here is a simple instance of its use:
IF option=1 THEN PROCmove_left
If the condition is true then execute the following statement(s) - a procedure call in the example. Several statements, separated by colons, can follow the THEN in which case all will be executed if the condition is true. Thus, for example:
IF option=1 THEN PROCcalc:PROCredraw:count+=1:flag=TRUE

If you look at other people's programs you will find many instances where the keyword THEN has been omitted. This normally causes no problems in practice, and whether to include THEN or not is largely a matter of personal style.

In the above examples no action occurs (or is specified) if the condition fails. This can be included using an ELSE clause, for example:
IF option$="plus" THEN PROCincrease ELSE PROCdecrease
The statements following the THEN or the ELSE can also include further IF-THEN or IF-THEN-ELSE statements, but it is often difficult to be sure of the logic of such constructions. Generally speaking, you should encounter few problems with ELSE IF, but try to avoid THEN IF. In outline, you should find that:
IF <condition> THEN <statements> ELSE
IF condition THEN <statements> ELSE
IF condition THEN <statements> . .

will work as expected.

Any problems that may occur can be avoided in Basic V by using a special block-structured IF-THEN. This takes the form:
IF <condition> THEN
<statements>
ELSE
<statements>
ENDIF

The 'statements' may include other IF-THEN-ELSE-ENDIF constructions, but no ambiguities will occur.

Here is an example of the use of this form of IF laid out to show its structure (LISTO7 will do this for you automatically).
IF FNfin_record(n%) THEN
PROCread_record(n%)
PROCdisplay_record(n%)
IF FNupdate_record(n%) THEN
PROCinput_data
PROCwrite_record(n%)
ENDIF
ELSE
PROCdisplay("Record not found")
ENDIF

The coding attempts to locate and possibly update a record in a data file, using clearly named procedure or function calls to do all the detailed work. There is one main IF-THEN-ELSE-ENDIF with another IF-THEN-ENDIF nested inside.

There is one important form of branching in Basic V which I have not covered this time, and that is the all-important CASE statement which handles multiple branching (although this can be achieved with nested IF-THEN-ELSE statements). This I hope to cover at some point in the future.

In conclusion, if you are to make the most of BBC Basic then it is important to be familiar with all the possible forms of looping and branching. If some of these are new to you then I suggest you deliberately try to include them in the next program which you write.