I started programming in GW-BASIC on an IBM PC clone running MS-DOS. Back then, many so-called home and business computers came bundled with a BASIC interpreter, mostly made by or licensed from Microsoft.

And they all looked similar. You were greeted by a screen with a READY or OK prompt and a blinking cursor waiting for your input. The “screen editor” and interpreter were all in one in the true sense of the word – they weren’t bolted together like the separate text editors and interpreters/compilers we use these days. You wrote your programs inside the BASIC interpreter, which also doubled as a line-oriented text editor.

To change a line, you first listed the approximate range of lines you were interested in with the LIST command. For example, LIST 100-200 would list all the lines starting with 100 and ending with 200, assuming they fit on the typical 25-line screens of the day. There was no scrolling, so if the line you wanted to change wasn’t visible, you had to specify a smaller range. Then, you would go to the line with the cursor keys, make your changes, and, this is very important, press the Enter key to save the new line. After that, you would go to an empty line and enter RUN to run your program.

Here’s a simple BASIC program, which prints out the squares of integers from 1 to N as specified by the user:

10 INPUT "How many numbers to square? Enter 0 to exit. ", N
20 IF N = 0 THEN END
30 FOR I = 1 TO N
40   PRINT I ^ 2
50 NEXT I
60 GOTO 10

The line numbers are typically incremented by 10 to allow for the addition of more lines in between at a later time. Thankfully, GW-BASIC had a useful RENUM command that would automatically renumber some or all of the lines in your program and update any referenced lines. You can think of it as an early example of automatic refactoring.

Enough with the peculiarities of GW-BASIC, though. Let’s go back to our BASIC program. I’ve written code in quite a few languages over some three decades, and I believe the BASIC program above is probably as short yet thorough as you can get in demonstrating how computers actually work to absolute beginners.

In just 6 lines, you get user input, store it in a variable, compare the variable with a value, run an operation inside a loop, and finally jump back to the beginning. There are no functions, no object oriented programming, no libraries, no frameworks – just a few simple instructions and jumps that can be directly mapped to machine code.

Once the beginner grasps the building blocks of programming –variables, conditionals, loops, and branching– you can start showing them how to reuse code. BASIC doesn’t have local variables or real functions, but it does have subroutines, which can be utilized with the GOSUB statement.

The following example program calls the text mode window drawing subroutine starting at line 1000 with 7 variables set: X, Y, W (Width), H (Height), FG (Foreground color), BG (Background color), TITLE$ (Title text of the window). The subroutine draws windows by using the ASCII codes of the line drawing characters.

5 COLOR 7,0: CLS
10 X=10: Y=5: W=30: H=8: FG=15: BG=1: TITLE$="Info": GOSUB 1000
20 X=20: Y=8: W=40: H=10: FG=15: BG=4: TITLE$="Warning": GOSUB 1000
30 COLOR 7,0: END
1000 'Draws a window with title bar
1005 COLOR FG,BG
1010 LOCATE Y,X: PRINT CHR$(213) 'Top left
1020 FOR I=1 TO W-2: LOCATE Y,X+I: PRINT CHR$(205): NEXT I 'Top
1030 LOCATE Y,X+W-1: PRINT CHR$(184) 'Top right
1040 FOR I=1 TO H-2: LOCATE Y+I,X: PRINT CHR$(179): NEXT I 'Left
1050 FOR I=1 TO H-2: LOCATE Y+I,X+W-1: PRINT CHR$(179): NEXT I 'Right
1060 LOCATE Y+H-1,X: PRINT CHR$(192) 'Bottom Left
1070 FOR I=1 TO W-2: LOCATE Y+H-1,X+I: PRINT CHR$(196): NEXT I 'Bottom
1080 LOCATE Y+H-1,X+W-1: PRINT CHR$(217) 'Bottom right
1085 FOR I=1 TO H-2: FOR J=1 TO W-2: LOCATE Y+I,X+J: PRINT " ": NEXT J,I 'Inside
1090 LOCATE Y,X+(W-LEN(TITLE$))/2-1: PRINT " "TITLE$" " 'Title bar
1100 RETURN

We just drew our own windows from top to bottom, complete with borders, using only 17 lines of code. Once again, we didn’t rely on any libraries, and just used the built-in BASIC statements. Here is the output of the program:


Two text-mode windows drawn on screen by a GW-BASIC subroutine. Two text-mode windows drawn on screen by a GW-BASIC subroutine.

“It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.” – Edsger Dijkstra

Now, obviously I don’t agree with Dijkstra here. Yes, BASIC lacks some universally agreed-upon programming concepts, and it does encourage the use of GOTO, which can easily lead to spaghetti code. However, at the lowest level, computer machine code doesn’t employ any of those concepts either. It’s just a bunch of CPU instructions and lots of jumping around.

If one wants to understand how computers work, I think it’s easier to start closer to the level they operate, and introduce useful abstractions like functional and object oriented programming as time goes on. Machine code and Assembly are too low level for beginners and even for veteran programmers. Popular programming languages like JavaScript and Python, on the other hand, are too high level – they’re far removed from the underlying hardware.

For me, BASIC feels about right as the first programming language. However, as soon as you start to feel its limitations, you should graduate to a modern language. I’m sure you will appreciate modern languages more once you’ve spent some time in BASIC, but you might also find that some modern languages and frameworks are more complicated than necessary.

Worth a look:

Discussed on:


Related: