Older Version Newer Version

Alyce Alyce Dec 9, 2009

Subroutines and Gosubs

by Alyce Watson

What is a Subroutine?


A subroutine is also called a subprogram. It is a self-contained section of code that can be called from other parts of the program. It can be called many times. If code that is to be reused many times is placed in a subroutine, the program has fewer lines of code. It is easier to read and to modify. Liberty BASIC has two kinds of subroutines, the GOSUB and the SUB.

Gosubs


A subroutine that is called by GOSUB [branchLabel] is part of the main program and shares its memory space. It begins with a branch label and ends with the keyword RETURN . When the RETURN keyword is encountered, the program execution returns to the next line after the GOSUB command that called the routine. Here is an example:

 Print "Starting program!" 
gosub [printHello]
print "Ending program!"
END

[printHello]
print "Hello, you are in a gosub!"
RETURN


GOSUB Rules



 'WRONG! 
[begin]
print "Hello World"

[myGosub]
print "I've visited a gosub!"
RETURN
'
'Right:
print "Hello World"
WAIT

[myGosub]
print "I've visited a gosub!"
RETURN


 firstName$="John" 
firstName$="Mary"
maxNum=45
maxNum=78

Called Subroutines


Called subroutines (subs) differ in many respects from GOSUB subroutines. The general form of a called subroutine is as follows:

 Sub SubName arg1, arg2,... argN 
'some code here
End Sub

The sub definition is signalled by the keyword SUB . It is followed by the sub's name, then a list of arguments, separated by commas. The argument list must not be placed inside of parentheses. The next lines contain whatever code routine is performed by the sub. The sub definition must end with END SUB .

 "Hello " + "World" 
"Hello " + UPPER$("World")
17 * 2 / 45
2 * (103 - 5)

The Argument List


The arguments sent to a called SUB may be string, numeric, or a mixture of both. They may be literal values, variables, or expressions. The arguments must be separated by commas. These arguments are actually variables that are local to the SUB. They can be used in code contained in the SUB. When the SUB ends, the variables no longer have any value. A SUB can exist without arguments, in which case the SUB name stands alone in the SUB statement line of code.

The names given to the argument list in the sub definition represent variables that are local to the SUB. When the SUB is called, whatever literal value, expression or variable is contained within the commas will be evaluated and given the corresponding name in the argument list. See the following examples for a demonstration of the argument list. Notice in the last example the variable names used to call the SUB have exactly the same names used in the SUB, but in a different order. (They are name1$ and name2$.) This doesn't matter, because the argument variables are local to the sub and are not the same variables as the ones with the exact same names used in the main program.

 call LongestName "Sam","Patricia" 

first$="Carl"
last$="Gundel"
call LongestName last$,first$

name1$="Liberty"
name2$="BASIC"
call LongestName name2$,name1$
end

Sub LongestName name1$,name2$
if len(name1$)>len(name2$) then
print name1$ + " is the longest."
else
print name2$ + " is the longest."
end if
End Sub

Results in:

Patricia is the longest.

Gundel is the longest.

Liberty is the longest.

Scope


Each SUB has its own memory space that is separate from the memory of the main portion of the program. Variables and branch labels that exist inside of the SUB do not exist in the main program. The main program cannot "see" them. Likewise, SUBs cannot "see" variables and branch labels that exist in the main program, or in other SUBs, or functions. The part of the program that can "see" a variable is called its "scope."

Some entities have global scope. That is, they can be seen both inside of SUBs and in the main program. These things are global in scope: arrays, handles (window and control handles, file handles, DLL handles, communications ports), and structs. In Liberty BASIC 4 variables can be declared as GLOBAL, which means that they can be seen from all parts of a program.

Special global status is given to certain default variables used for sizing, positioning, and coloring windows and controls. These include variables WindowWidth, WindowHeight, UpperLeftX, UpperLeftY, ForegroundColor$, BackgroundColor$, ListboxColor$, TextboxColor$, ComboboxColor$, TexteditorColor$. The values of these variables can be seen in any SUB. If these variables are used in any way, they become local to the sub. For instance, a window opened inside a sub will open with a width equal to the current WindowWidth. If WindowWidth is referred to in any way, it becomes local to the sub. As an example, if the sub includes this line:


 ww = WindowWidth 

WindowWidth no longer has the value it has outside the sub. To test this try the following small demo.


 print WindowWidth 

call ShowWindowWidth
end

Sub ShowWindowWidth
print WindowWidth
End Sub


The results of the program:

320

0

Calling SUBs


SUBs are called by using the keyword CALL followed by the name of the sub, then a comma separated list of arguments. When the SUB exits, program execution returns to the line after the CALL command.

SUB Rules


  1. SUBs don't need input arguments.
  2. SUB names are case sensitive. mysub does not refer to the same routine as MySub.
  3. SUBs may contain code that calls Liberty BASIC functions or other user-defined functions or subs.
  4. Code should never step into a SUB from the main program. A SUB should always be called explicitly. Code should not flow into a SUB. A WAIT statement, an END statement, or a GOTO [branch] stops program flow from entering a sub.


 'WRONG! 
Call MySub 1,2

Sub MySub num1,num2
print num1+num2
End Sub
'''''''''''''''''''''''''''
'RIGHT!
Call MySub 1,2
wait 'this line halts the program so it doesn't enter the function

Sub MySub num1,num2
print num1+num2
End Sub

SUBs as Event Handlers


Liberty BASIC 4 allows us to use Subs as event handlers. In previous versions of Liberty BASIC, branch labels were used as event handlers. When a Sub is used as an event handler, the argument list contains things like the handle of the control or window that fired the event, the MouseX and MouseY values, and the value of Inkey$. See the article by Janet Terra called Coding with Sub Event Handlers . Here is a small example of a button event handler Sub.


 nomainwin 
button #main.exit, "Exit", exitClicked, UL, 10, 10
open "Button Example" for window as #main

[loop]
wait

sub exitClicked buttonhandle$
notice "The button handle is ";buttonhandle$;" Goodbye."
close #main
end
end sub

Subroutines in Action


Here is a demo that changes the case of all words in a string so that the first letter is uppercase and the remaining letters are lowercase. Run the little demo to see how it works. Notice that the code inside the SUB uses several native Liberty BASIC string functions.

 call NameCase "hello world" 
call NameCase "CARL GUNDEL"
call NameCase "tiTaNiC"
end

Sub NameCase name$
nm$=word$(name$,1)
while nm$<>""
i = i + 1
nm$=word$(name$,i)
first$=upper$(mid$(nm$,1,1))
rest$=lower$(mid$(nm$,2))
new$=new$+" "+first$+rest$
wend
print "Name is now ";trim$(new$)
End Sub

Here is a simple numeric SUB that prints the average of three values.

 call Average 15,88,20 
call Average 10,20,30
end
Sub Average num1,num2,num3
print "Average is ";(num1+num2+num3)/3
End Sub

Here is the same routine, but this one uses a GOSUB subroutine. GOSUB subroutines do not accept input arguments, but they can "see" values in the main program, because they are actually part of the main program and share its memory space. Note the differences between the two methods:

 num1=15 
num2=88
num3=20
gosub [Average]

num1=10
num2=20
num3=30
gosub [Average]

end

[Average]
print "Average is ";(num1+num2+num3)/3
RETURN

GOSUB or SUB?


Use a GOSUB routine when:


Use a called SUB when: