Sub-Procedures
(SUBs)

When programs get big, you need to break them into smaller pieces that are easier to work with. QBASIC calls these pieces "sub-procedures" or SUBs. Other programming languages have other names, like procedures, subroutines, or subprograms.

To work with SUBs in QBASIC, we need to look at the "SUBs" dialog box which shows us a list of our SUBs. Select "View | SUBs..." from the menu to bring up the SUBs dialog box. You can also press the F2 key to get there more quickly. In here, you can select a SUB to work with, or you can select the main module. If you are just starting with a clean slate (File | New) you'll see that the main module is called "Untitled", and there are no SUBs.

You can define a new SUB in QBASIC simply by typing it in. This will jump you to the view of the new SUB. Try typing this:

    SUB DrawCircle
      CIRCLE (320, 240), 100, 15
    END SUB

Notice that after you pressed enter on the first line, you were taken to a new screen with just your new SUB in it. Now, if you go to the SUBs dialog box (View | SUBs...), you can see that you have a SUB named "DrawCircle" and a Main Module named "Untitled".

Now we need to go back to the Main Module ("Untitled") to actually use the new SUB. From the menu, select View | SUBs... to get the SUBs dialog box. Now double-click on "Untitled" to get back to the Main Module. The screen will go blank, but don't worry, your SUB is still out there. Now type this in and run it:

    SCREEN 12
    CLS
    DrawCircle

See? DrawCircle did what it was supposed to do.

Let's try adding another SUB. See if you can remember the steps on your own. Refer back to the previous example if you need help.

    SUB PlayMary
      PLAY "e8 d8 c8 d8 e8 e8 e4"
    END SUB

Now we need to change the Main Module to use our new SUB. So, go back to the Main Module, and change it to look like this:

    SCREEN 12
    CLS
    DrawCircle
    PlayMary

Now run it and you should see the circle and hear the song.

Dividing programs into smaller pieces like this will help you make sense out of big programs.

Arguments

Sometimes you want to pass numbers or strings to a SUB. QBASIC lets you do this. Here is a new version of the DrawCircle SUB:

    SUB DrawCircle2 (Radius)
      CIRCLE (320, 240), Radius, 15
    END SUB

This version lets us pass in the Radius. When we do this, Radius is called a "parameter" or "argument" to our SUB. Here's how we would then pass an argument from the Main Module:

    SCREEN 12
    CLS
    DrawCircle
    DrawCircle2 (20)
    PlayMary

We could also do something like this in our Main Module:

    SCREEN 12
    CLS
    FOR I = 5 TO 200 STEP 5
      DrawCircle2 (I)
    NEXT I

Changing Arguments

If you need to tell the main module something, you can change one of the arguments in your SUB, and the main module will see the change.

    SUB AddOne(X)
      X = X + 1
    END SUB

    CLS
    I = 0
    AddOne(I)
    PRINT I

When you run that program, it will print the value 1 on the screen. This is because the value of I is changed by the AddOne SUB. If you only need to return one value, a FUNCTION is sometimes a better choice. FUNCTIONs are described later.

Scope

What if we had variables in the Main Module and in a SUB that happen to have the same name. Would they be the same variable? Let's find out. Enter this SUB:

    SUB Scope
      PRINT "Scope says: "; X
      X = 23
    END SUB

And this Main Module:

    X = 15
    Scope
    PRINT "Main Module says: "; X

And run it. What happened? Scope said "0" because to Scope, X was a new variable. Main Module said 15, because Scope didn't change Main Module's X, it changed it's own X. Scope's X and Main Module's X are different variables.

Variables that you create in a SUB cannot be seen by the Main Module. Variables in the Main Module cannot be seen by a SUB. If you need to share variables, you can pass them as arguments to the SUB.

Global Data

It is possible to make variables in the Main Module available to SUBs without passing them as arguments. Most programmers consider this dangerous since you never know who might change those variables. Add a "SHARED X" to the Scope SUB like this:

    SUB Scope
      SHARED X
      PRINT "Scope says: "; X
      X = 23
    END SUB

Now when you run it, you'll see that Scope can now see the Main Module's X. Scope no longer has its own X. This is called "Global Data", and should be avoided if you can.

You can also make a variable global to all SUBs from the Main Module like this:

    DIM SHARED X

Object Oriented Programming

When you start worrying about SUBs and the Main Module sharing variables, you are probably ready to begin learning Object Oriented programming. Object Oriented programming makes it easier to share variables between SUBs and still write code that is easy to understand. Visual BASIC, Java, and C# are programming languages that provide Object Oriented programming features, and are fairly easy to learn.

STATIC

Notice that each time you call a SUB, its variables are lost after the SUB is over. Here's an example:

    SUB Counter
      C = C + 1
      PRINT C
    END SUB

    CLS
    Counter
    Counter
    Counter

Not a very good counter, since it always prints "1". We can use STATIC to tell QBASIC that we don't want C to go away after the SUB is over. Then we will get the behaviour we expect. Change the Counter SUB like this:

    SUB Counter
      STATIC C
      C = C + 1
      PRINT C
    END SUB

That's much better.

Object Oriented programming languages offer many ways to avoid the use of STATIC variables. If you find yourself making lots of STATIC variables, it is probably time to learn an Object Oriented programming language.

Functions

Functions are just like SUBs, but they return a value. Here's an example:

    FUNCTION Add (X, Y)
      Add = X + Y
    END FUNCTION

And here's a Main Module to go with it:

    PRINT Add(3, 4)

Well, I DECLARE!

As you've been entering the example programs in this chapter, you may have noticed that the QBASIC editor adds "DECLARE" statements to the programs. Why does it do this? The DECLARE statement is a warning to QBASIC to let it know that there are SUBs or FUNCTIONs in this program. Without this warning, QBASIC would have no idea what we mean when we call a SUB or FUNCTION. It would think it had found a syntax error and the program would stop.

Fortunately, QBASIC handles making DECLAREs for us. Unfortunately, in larger programs, it might put the DECLAREs someplace that looks ugly. Fortunately, you can move the DECLAREs anywhere you want (as long as it is before the FUNCTION or SUB is first used) and QBASIC still takes care of the rest.