Your Spectrum
Issue 3, May 1984 - QL User supplement
Home QL User index
Holy Structures ...
It's SuperBasic

Zap, Pow, Blam ... just when you thought it was safe to get back to unstructured waters, along came the Cambridge Joker in his QL-Mobile with a surprise present - SuperBasic - to threaten an imprecise programming world. Andrew Pennell battles to explain ...
The subtly named SuperBasic on the QL appears to have interesting features, particularly its ability to use Pascal- like structures, similar to BBC Basic. I say 'appears' because at the time of writing (some weeks after the 28-day expiry) no QLs have been manufactured; this article is based mainly on information given in the provisional User Guide and therefore no guarantees can be given as to its total accuracy.
Having thus 'copped out', let's first of all consider the subject of structured programming. Different people have different views, but for me it's programming in such a way as to be 'self- documenting' - that is, you're able to work out what a section of program does without too much effort. The much maligned GO TO and GO SUB statements have long come under attack by purists - certainly they make program flow more difficult to follow on paper. The QL manual says that the extra SuperBasic commands make these statements superfluous, and there's a lot of truth in it. When I was taught Pascal, I remember the lecturer putting a total ban on the GO TO statement, which horrified me at the time. But she was right - you don't need it in Pascal, and you shouldn't need it in SuperBasic, if you use the control structures efficiently; none of the QL programs in this article have it.
There are four major enhancements to bog- standard Basic in the QL that relate to structured programming - functions, procedures, REPEAT loops and the SELECT command. They are very similar to certain Pascal statements, except that SELECT in SuperBasic is known as CASE in Pascal. I shall endeavour to show you each of them in use, and compare them to their 'equivalent' in Spectrum Basic.


QL-type functions are a great improvement on Spectrum types allowing as they do multi- line definitions and the use of local variables. On the Spectrum, DEF FN statements could only be followed by an
expression, with no other statement types allowed. Any attempts at recursion (ie. the function calling itself) resulted in an 'Out of memory' error, after a delay while the machine stack filled. SuperBasic functions, on the other hand, do allow recursion, as well as single- line definitions with the normal syntax.
An example of a recursive function is shown in Listing 1a, where a function called 'fact' calculates the factorial of a number. (The factorial of a number is the result of all integers up to and including it being multiplied together - eg. factorial 4 = 1x2x3x4 = 24.) Lines 1010-1020 check first for factorial zero, which by definition
"The QL manual says that the extra SuperBasic commands make the GO TO and GO SUB statements superfluous"
is '1'. It does this by using the QL IF ... THEN ... ELSE commands, and RETURN 1 is the way to return a value of one of the function. If it's not zero, then lines 1030-1040 make the function return a value calculated from another factorial, hence the recursion.
The Spectrum version is shown in Listing 1b and it has several disadvantages when compared to the QL version - and that's apart from its lack of structure. In particular, the variable i is corrupted by the routine, and the 'input' variable must always be a, and the 'output' variable is always fact. With the QL version, there are no variable restrictions - if you wish to make zz equal to the factorial of b, then you could use zz=fact(b).
As you can see, to use a QL function you don't need the FN of other Basics - you just use it like any of the built-in functions.
Listing 2a shows another QL function, which is used for a 'live' string input routine called 'getstring$'. It shows several of the QL's features, the first of which is LOCAL. If you want to use variables in a function definition (or in procedures, shown later) and you don't want them to affect any variables in the rest of the program, then the use of LOCAL will ensure that the values of any existing variables with the same name are preserved through the function or procedure, then restored afterwards.
Another 'structured' feature is the REPEAT command, used for looping. Basically, if you want a loop of some sort, put 'REPEAT some name' at the start, and 'END REPEAT somename' at the end. Then, where you want to put a test to leave it, use 'IF condition THEN EXIT somename' and the named loop will no longer execute. Unfortunately, this is not very similar to either Pascal or BBC Basic's REPEAT ... UNTIL construct, making conversion more difficult.
The final, rather neat, feature used is the SELECT statement, which allows easy choices to be made without unwieldy IF ... THEN statements - something which has not been implemented on any previous Basic. Line 1010 ensures first that any variables called a$ or b$ in the calling program are not affected, and then it enters the main loop, 'getloop'. The two REPEATs in lines 1030 and 1040 are short forms of the statement, and execute the multi- statements that come after them automatically without END REPEAT commands; they're used in the function to scan the keyboard.
Lines 1050-1170 consist of SELECT statements for taking a number of different actions, depending on the key used. If Newline (CHR$ 13) is pressed, then the main loop, 'getloop', is left. If backspace (CHR$ 8) is pressed, then (if allowed) a backspace is printed and a character removed from the end of b$. Note that QL string handling is conducted in the same (non- standard but neat) way as the Spectrum and ZX81. If it's a non- control character (lines 1120- 1160) it's printed, then added to b$.

Finally line 1190 ensures that the value returned from the function is b$.
For reference, the Spectrum equivalent is shown in Listing 2b and it displays similar disadvantages to Listing 1b. I've made one assumption in the QL version, and that is that backspace is CHR$8 (it should be as it's the ASCII standard code).
As well as functions, the other major structure addition is that of procedures. A procedure is a sequence
of instructions, optionally using parameters, which is basically just an upmarket GO SUB. They each must have a different name, and are invoked by simply using their names, unlike fussy BBC Basic which requires PROCname. This allows extra commands to be added, without resort to the machine code that's required when adding commands to the Spectrum - and the BBC Micro for that matter.
In Listing 3a, a QL procedure
called 'box' is defined which, not surprisingly, draws a box that's defined by its bottom left-hand corner, its width and height. The QL has an improved version of DRAW, which can cope with many parameters, each separated with TO. To use it, for example, to draw a box at (10,20), size 300x200, is simply: box 10,20,300, 200.
Note that unlike DEF PROC no brackets are required when the procedures are actually used. The Spectrum
SuperBasic - A Spectral Comparison
1000 DEF FN fact(a)
1010 IF a=0 THEN
1020  RETURN 1
1030 ELSE
1040  RETURN a*fact(a-1)
1050 END IF
1060 END DEF

Listing 1a
1000 LET fact=1
1020 FOR i=1 TO a
1030 LET fact=fact*i
1040 NEXT i

Listing 1b
This is an example of recursion, where the function 'fact' calculates the factorial of a number. Note the use of QL keywords IF ... THEN ... ELSE. The Spectrum Basic version of Listing 1a - you can see that there are a number of variable restrictions; ie. the variable i is corrupted by the routine.
1000 DEF FN getstring$
1010 LOCAL a$,b$
1020 LET b$=""
1025 REPEAT getloop
1030  REPEAT getpause: IF INKEY$="" THEN EXIT
1040  REPEAT getkey: LET a$=INKEY$: IF a$<>""
THEN EXIT getkey
1060   ON CODE a$=13
1070    PRINT : EXIT getloop
1080   ON CODE a$=8
1090    IF b$<>"" THEN
1095     b$=b$( TO LEN b$-1)
1100     PRINT CHR$ 8;" ";CHR$ 8;
1110    ENDIF
1120   ON CODE a$=32 TO 127
1130    IF LEN b$<32 THEN
1140     b$=b$+a$
1150     PRINT a$;
1160    ENDIF
1180  END REPEAT getloop
1190 RETURN b$
1200 END DEF

Listing 2a
1000 LET b$=""
1010 PAUSE 0: LET a$=INKEY$
1020 IF CODE a$>127 THEN GO TO 1010
1040 IF a$<>CHR$ 12 THEN GO TO 1100
1049 REM backspace
1050 IF b$="" THEN GO TO 1010
1060 LET b$=b$( TO LEN b$-1)
1070 PRINT CHR$ 8;" ";CHR$ 8;
1080 GO TO 1010
1100 IF LEN b$=32 OR CODE a$<32 THEN GO TO 1010
1110 LET b$=b$+a$
1120 PRINT a$;
1130 GO TO 1010

Listing 2b
This program example illustrates a 'live' string input routine called 'getstring$'. Notable QL features to watch out for are the LOCAL, REPEAT and SELECT commands. The equivalent Spectrum Basic to Listing 2a, although seemingly shorter, is somewhat lacking in structure. The problem of variable restriction is also present.
1000 DEF PROCbox(x,y,width,height)
1010 PLOT x,y
1020 DRAW x+width,y TO x+width,y+height
1030 DRAW x,y+height TO x,y
1040 END DEF

Listing 3a
1000 PLOT x,y: DRAW width,0
1010 DRAW 0,height: DRAW -width,0
1020 DRAW 0,-height

Listing 3b
This QL procedure draws a box by defining its bottom left- hand corner, width and height. More complex parameters may be included, separated by the keyword TO. Spectrum Basic allows the routine in Listing 3a to be written in a simpler fashion - it uses a DRAW statement that is relative, rather than the QL's absolute equivalent.
1000 DEF PROCpformat(b)
1010 LOCAL a,a$
1020 a=(INT (b*100))/100
1030 IF a<.01 THEN PRINT "     0.00";: RETURN
1040 IF a>1e6 THEN PRINT "     ?.??";: RETURN
1050 a$=STR$ a
1060 IF a$(1)="." THEN a$="0"+a$
1070 IF a$(LEN a$-1)="." THEN a$=a$+"0"
1080 IF a$(LEN a$-2)<>"." THEN a$=a$+".00"
1090 REPEAT strlen
1100 IF LEN a$=9 THEN EXIT strlen
1110 a$=" "+a$
1120 END REP strlen
1130 PRINT a$;
1140 END DEF

Listing 4a
1000 LET a=(INT (a*100))/100
1010 IF a<.01 THEN PRINT "     0.00";: RETURN
1020 IF a>1e6 THEN PRINT "     ?.??";: RETURN
1030 LET a$=STR$ a
1040 IF a$(1)="." THEN LET a$="0"+a$
1050 IF a$(LEN a$-1)="." THEN LET a$=a$+"0"
1060 IF a$(LEN a$-2)<>"." THEN LET a$=a$+".00"
1070 IF LEN a$<9 THEN LET a$=" "+a$: GO TO 1070
1080 PRINT a$;

Listing 4b
This procedure is suitable for a financial package in which you wish to right- justify a series of numbers on the decimal point. Again, use is made of the LOCAL and REPEAT commands. To simulate Listing 4a in Spectrum Basic, you come up against the same problem experienced in Listing 1b - namely, that of variable restrictions; ie. you lose the old values of the variables a and a$.

version, in Listing 3b, is a bit simpler than the QL version because it uses a relative DRAW statement, whereas the QL's is absolute.
Listing 4a shows another QL procedure called 'pformat', which prints a number right- justified on the decimal point and therefore it's for printing currency. It's probably called 'pformat' because format is a reserved word; there's already a Basic statement with that name. It uses a LOCAL statement, as well as a REPEAT loop to finally right- justify the output string, a$. It uses the STR$ command, found on most other Basics but missing from the SuperBasic manual. Because of the variable coercion on the QL, it may well be possible to replace it with: 1050 a$=a.
The equivalent Spectrum program is shown in Listing 4b, and its main disadvantage is again the loss of the old value of variables, a and a$.
The use of procedures greatly enhances the readability of programs if
"SuperBasic has some interesting features, particularly its ability to user Pascal- like structures, similar to BBC Basic"
used properly and, with sensible names. As an example:

100 print_instructions
110 setup_game
120 play(speed)
130 do_highscore

is much more understandable than a possible Spectrum equivalent of:

100 GO SUB 9000
110 GO SUB 2300
120 GO SUB 4200
130 GO SUB 1200

The way that functions and procedures add features to QL Basic is extremely useful, so much so that on switching on your QL, it will ask you if you want to LOAD any from Microdrive.
I hope this has given an insight into the 'structured' aspects of SuperBasic on the QL; you can all practice now while waiting for one to be delivered. Who knows, if it really catches on, it could be the end of the GO TO for good!

[continued overleaf ...]
Home QL User index