What was wrong with BASIC?

The BASIC programming language was introduced in 1964 at Dartmouth College by John Kemeny and Thomas Kurtz. It was one of the first time sharing systems, where students could sit behind a teletype and begin typing their programs and start running them immediately. In those days it was far more common that you had to type your program on punched cards, hand it over to the computer centre and get your printout back after a few hours.

BASIC was easy to learn and it was useful to university students who were not computer specialists. It supported many mathematical functions and early on, it supported matrix operations, a feature that got lost when BASIC was later ported to microcomputers. And what else got lost too?

No Structured Programming

The earliest versions of Dartmouth BASIC did not support structured programming, other than the FOR..NEXT loop. BASIC used line numbers for two different purposes:

  • To support editing of programs. Terminals were teletypes that printed everything you typed on paper. There was no computer screen , where you could move the cursor around and start editing code anywhere in your program. The internal editor kept the program ordered by line number. If you want to insert a line into a program, you simply enter a line with an intermediate line number (therefore you started your program using line numbers that incremented by 10, so there were intermediate numbers). By entering a line with an existing number, you replace that line. When you enter the line number by itself, you delete that line.
  • As labels for GOTO and GOSUB.

At least in FORTRAN, you had labels only at lines to which you wanted to jump. In BASIC, every line could be jumped to. This may be somewhat easier to learn, but it made programs harder to maintain.

The first version of FORTRAN had no subroutines at all, but all versions after that, had named subroutines, with local variables and named parameters. Nothing of that in early BASIC. In BASIC you had GOSUB to a line number. With Assembly language you could at least give your subroutines meaningful names. This was not the case with early versions of BASIC (including early versions for microcomputers). That made BASIC feel like an even lower level language than Assembly language in that respect. If you renumbered your program to get the line numbers less haphazard, your subroutines would change line numbers.

The very earliest BASIC could only specify line numbers in an IF statement, for example:IF A<B THEN 30 ELSE 50

All versions of Microsoft BASIC I know, did allow you to execute one or more statements conditionally, so you did not need line numbers and implied GOTO statements for all IF statements, for example IF A<B THEN PRINT "TOO LOW": C=C+1

Not all versions of Microsoft BASIC had ELSE though. And ANSI Minimal BASIC only supported the variant with line numbers, as did TI BASIC.

Too Much Variation

Microsoft was the main developer of BASIC implementations for microcomputers. But Sinclair, Acorn and TI had their own implementations of BASIC. There was very little that the BASIC versions had in common. Some only supported variable names of a single letter (Sinclair, other than numeric scalar variables), others allowed arbitrary length names. Most had string variables that allowed strings of variable length, but some versions of BASIC had all strings in a string array the same length (Sinclair).

Even within Microsoft itself, there was a wild difference between the commands and functions supported. For example, some BASIC versions supported user-defined functions, but only with numeric values and a single numeric parameter. Others supported both string and numeric functions with an arbitrary number of parameters of any type. Some BASIC versions did not have user defined functions at all. In some versions of Microsoft BASIC you had long variable names, all characters significant, but in other versions, only the first two characters of a variable name counted. So the variables DEBT and DECLARED would be the same. And if you dared to use a variable name MORTGAGE, the parser would mix up and tokenise the letters OR into a single byte (the OR operator). This happened only in some versions of Microsoft BASIC (for example MSX BASIC), but not in others (for example GW-BASIC on MS-DOS). On some computer systems, the disk BASIC was not even compatible with the cassette BASIC on the same machine.

Acorn introduced BBC BASIC in 1981. It had structured loops like REPEAT..UNTIL, it had named procedures and named multi-line functions, while it was still largely compatible with the then current versions of Microsoft BASIC. Later versions of BBC BASIC added a full block-structured IF-THEN-ELSE-ENDIF, a proper WHILE loop and more. Procedures and functions did had parameters and local variables.

Unfortunately, BBC BASIC completely ignored the ANSI standard for full BASIC. Microsoft did not. When they introduced Quick Basic and later QBASIC, they had named subroutines (with local variables and parameters) and the usual block-structured constructs, but they were completely different from those of BBC BASIC.

You really can’t call two versions of BASIC the same language if the basic constructs for named subroutines or procedures are so different. You might as well call Ada and Pascal the same language.

Specialised Syntax

In BASIC, each command tends to have its own unique syntax. For example, the PRINT statement uses commas and semicolons between parameters to determine how the output will be formatted. A numeric parameter starting with # specifies a file to print to. Many BASIC versions have a USING parameter to allow formatted output. We have funny specialised syntaxes in Microsoft BASIC for OPEN (admittedly quite readable), like : OPEN "name" FOR INPUT AS #1

And we have funny little syntaxes for line drawing, like LINE (100,100)-(200,150)

User-defined subroutines always have to be called with CALL, like CALL MYSUB(10,20)

They are not allowed to look like normal BASIC commands and they can certainly not have the same wild syntax variations as built-in commands.

Pascal commits the same sin to a lesser degree. Pascal is very rigid in not allowing procedures with a variable number of parameters or parameters of different types. But the built-in procedures read and write can have a variable number of parameters and parameters of many different types. Add to this the weird formatting syntax like write(a:12:7); to specify that the number A must be printed with 12 characters and 7 digits after the decimal point. But other than the colon formatting syntax, calls to read and write look like ordinary procedure calls.

C on the other hand,has no specialised syntax for printf or fopen. These are just ordinary functions. the printf function does have a variable number of arguments and it is somewhat of a challenge to implement such a function, but it can be done. Details of the I/O library are not baked into the syntax of the language itself.

And the Good Things?

Of course, BASIC did have some good things too:

  • Most versions of BASIC supported variable length strings and quite a few functions to manipulate strings. Standard Pascal lacked a variable length string type and the language went out of its way to make you suffer. You ended up counting out spaces to make all messages the same length, for example if they had to be passed as parameters. Turbo Pascal did have a usable string type, but with extensions like this, there is no standardisation among implementations.
  • Data embedded in the program. READ, DATA and RESTORE may look clumsy compared to initialised C arrays, but standard Pascal did not have a way to embed data in the program itself. You had to read it from file or you had to type endless lines of assignment statements to initialise the elements of an array.
  • Low memory usage. This was key in early microcomputers. A simple Microsoft BASIC fit into 8 kilobytes of ROM and programs were stored in RAM in such a way that every keyword occupied one byte. There was no separate storage of source code and parsed byte code. The LIST command showed you the program as you had typed it, with all byte tokens converted back to full keywords and all binary representations of line numbers printed in decimal.Interpretation was usually rather slow, but it got done with very little memory.
  • Floating point support and a full set of mathematical functions. Apart from integer BASIC versions of some very stripped down versions, you had full trigonometric and logarithmic functions.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *