Programming In BASIC
Using True BASIC:
Subroutines, Functions, Modules
BY DELMAR SEARLS
Convert numbers from any base to any other. This program, with sample source code in ASCII format, is in BASCNVRT.ARC on your START disk.
In the February 1989 issue of START we introduced a continuing series on True BASIC. This issue, take a look at how True BASICs subroutines, functions and modules are structured. If you own True BASIC, brush up on these concepts and follow along with the sample program on disk. If you're just curious about True BASIC, read on to see if this full-powered, interpreted language will meet your needs.
We All live in a Yellow Subroutine
In True BASIC the definition of a subroutine starts with the keyword Sub and ends with End Sub.
Sub Name(Parm1, Parm2,. . . ) Body of Subroutine End Sub
A subroutine is invoked by the statement
Call Name(Value1, Value2,. . .)
where Name is the name of the subroutine and Value1, Value2,. . . correspond to Parm1, Parm2,. . . respectively. For example, Parm1 in the subroutine has as its initial value Value1 from the Call statement.
The purpose of a subroutine is to execute a group of commands. The primary purpose of a function, on the other hand, is to return a single result. The definition of a function begins with Def and ends with End Def.
Def Name(Parm1, Parm2,. . . ) Body of Function Let Name = Result End Def
Somewhere within the definition, Name must be assigned a value. In the example, the assignment came at the end of the function. While this is often the case, the assignment can be made anywhere within the function.
A function is used just as if it were a variable name.
Let X = 3 * Cuberoot(A) Print Average(Numlist)
In the first example Cuberoot is a function with one numeric parameter. In the second, Average has an array parameter and returns the average of the numbers in the list. This value will be printed on the display device.
Parameters and Arguments
In the definitions above, Parm1, Parm2,. . . are parameters. Value1, Value2,. . . are values (variables, constants or expressions) and are called arguments. When a subroutine or function is used, Parm1 takes on Value1, Parm2 takes on Value2 and so on. The parameters and arguments must agree in number and each pair (e g. Parm1 and Value1) must be of the same type (either numeric or string).
The arguments of a function are passed by value. The value of each argument is passed to the function and copied into a temporary storage location (corresponding to the name of the parameter). If a parameter is altered, it does not affect the actual argument since only the copy was altered.
However, the arguments of a subroutine are passed by reference. The address of the argument is passed to the subroutine. If the argument name is X and the parameter name is Num, both X and Num identify the same storage location in memory. Consequently if Num is altered within the subroutine, the value of X is also altered because they both refer to the same location.
Passing by reference is limited to variable arguments. If the argument of a subroutine is a constant or an expression, then a temporary storage location is created and its address passed to the subroutine. True BASIC can be tricked into passing even a variable argument by value rather than reference.
Call Do_it(A, B)
This statement invokes the subroutine Do_it and passes the addresses of variables A and B.
Call Do_it(A, (B))
This statement invokes the same subroutine and passes the address of A. However, because the variable B is in parentheses True BASIC thinks it is evaluating an expression. Consequently a temporary storage location is created and the value of B is placed in it. The address of this temporary location is passed to the subroutine. Thus any changes made to the corresponding parameter in the subroutine will not affect the value of B, only the value in the temporary location.
One final observation needs to be noted. Arrays can only passed by reference to subroutines since there are no array expressions in True BASIC. Passing arrays to functions is time-consuming because a local copy of the entire array must be made each time the function is invoked.
Internal Versus External
An internal function or subroutine is one which appears before the End statement in a True BASIC program. All of the variables in an internal program unit are global. For example suppose that the variable Index is used in the main program and in an internal subroutine. They would both refer to the same memory location. Any change to Index in the subroutine would change the value of Index in the main program as well. (Note that we are not talking about parameters here, just about variables that are used in a subroutine or function.)
An external function or subroutine follows the End statement. All variables used in external program units are local. That is, they are known only within the unit. Suppose Index is used in the main program and in an external function. They refer to two different memory locations. When the function is invoked a temporary storage location is created and identified by Index. Any use of Index in the function refers to that temporary location. When the function terminates, this temporary location is released. References to Index in the main program will refer to the storage location created by the main program itself.
Generally speaking, external subroutines and functions are preferred to internal ones. The main reason is that the variables in external units are local. Many a programmer has wasted hours searching for the cause of a program error only to discover that a variable identifier (in a global environment) was inadvertently used for two different purposes.
True BASIC Modules
A True BASIC module is a collection of external subroutines and functions having two distinct properties. First, the subroutines and functions can share data (including arrays) that are stored independently of the main program and that cannot even be accessed by the main program directly. The only access allowed by the main program is through the subroutines and functions in the module.
Normally, external functions and subroutines allocate space for local storage when invoked and release the storage when they are done. In a module, however, data storage (for shared data) is permanently allocated.
Furthermore you can specify which subroutines and functions in a module can be accessed from outside and which cannot. Those declared to be private can only be accessed by subroutines and functions within the module itself. Thus the programmer is able to limit access to the module to only a limited number of subroutines and functions.
Consider a program that maintains its own data stack. In BASIC the stack would normally be implemented as an array. Subroutines to Push values onto the stack or Pull values from the stack would either have to be internal (accessing the stack as a global variable) or external (passing the stack as an argument). Using internal program units to access the stack requires additional care in choosing the names of variables since all the variables would be global.
Incorporating the stack (and the routines that directly manipulate it) within a module allows us the best of both worlds. We can use external subroutines, with their local variables, to access the stack without passing the stack as a parameter. We can hide the details of the stack and worry only about the logical operations Push and Pull. The details are handled by the module. Inadvertent changes to the stack are all but impossible. Finally, once a module is written, it can be freely incorporated into any program needing its services with a minimum of effort.
The program BASCNVRT.TRU illustrates the use of subroutines, functions and modules in True BASIC. Copy BASCNVRT.ARC and ARCX.TTP onto a blank, formatted disk and un-ARC the file, following the Disk Instructions elsewhere in this issue. BASCNVRT is extensively documented so I won't go into details here. It allows you to convert numbers in any base (2 to 16) to any other base. You can execute the runtime version, BASCNVRT.PRG, from the Desktop even if you don't own True BASIC.
Watch this column for more on True BASIC. Next up: Using True BASIC to write great, portable graphics programs.
Delmar Searls is the author of Grapher in the Fall 1987 issue of START.
True BASIC language system and runtime package, $99.95 True BASIC Inc, 45 Theodore Fremd Avenue, Rye, NY 10580, (800) 872-2742; technical support: (603) 298-5655