Liberty BASIC Help Online |
Functions and Subroutines
Liberty BASIC supports user defined functions and subroutines. They look similar to their QBASIC equivalents:
'define a function for returning a square root
function squareRoot(value)
squareRoot = value ^ 0.5
end function
and...
'create a subroutine for logging to an event log
sub logToFile logString$
open "c:\logdir\event.log" for append as #event
print #event, time$()
print #event, logString$
close #event
end sub
A user-defined function such as the one above can be treated like any built-in function:
print "The square root of 5 is "; squareRoot(5)
Subroutines in Liberty BASIC are accessed using the CALL statement. For example:
'Now log some info to disk
call logToFile "The square root of 5 is " + squareRoot(5)
The variable scoping in subroutines and functions is local. This means that by default, the names given to variables inside the definition of a subroutine or function are only meaningful inside that definition. For example, a variable named "counter" can exist in the main program code. The program can use a function which also contains a variable named "counter" in its code. When the function is used, the "counter" variable in the calling code doesn't lose its value when the function changes the value of its variable named "counter". They are in fact different variables, although they share the same name. Variables passed into subroutines may be passed by reference, which allows them to be changed in the subroutine or function, and the change is reflected in the main program. For more on passing byref, please see below.
Here is an example that uses a function:
'set my variable counter
for counter = 1 to 10
print loop(counter)
next counter
end
function loop(limit)
for counter = 1 to limit
next counter
loop = counter
end function
Exceptions to the variable scoping mechanism include the following things which are globally visible everywhere in a Liberty BASIC program:
- Arrays
- Things with handles (files, windows, DLLs, communications ports)
- Structs
In general, variables used in the main program code are not visible inside functions and subroutines. Variables inside functions and subroutines are not visible in the main program. Liberty BASIC 4 introduces the GLOBAL statement to create global variables. Variables declared as GLOBAL can be seen everywhere in a program. See GLOBAL. The special system variables lWindowWidth, WindowHeight, UpperLeftX, UpperLeftY, ForegroundColor$, BackgroundColor$, ListboxColor$, TextboxColor$, ComboboxColor$, TexteditorColor$, DefaultDir$, Joy1x, Joy1y, Joy1z, Joy1button1, Joy1button2, Joy2x, Joy2y, Joy2z, Joy2button1, Joy2button2, and Com now have true global status. GLOBALS are specified and used like this:
'define a global string variable:
global title$
title$ = "Great Program!"
'Special system variables don't
'need to be declared as global,
'since they have that status automatically
BackgroundColor$ = "darkgray"
ForegroundColor$ = "darkblue"
'call my subroutine to open a window
call openIt
wait
sub openIt
statictext #it.stext, "Look Mom!", 10, 10, 70, 24
textbox #it.tbox, 90, 10, 200, 24
open title$ for window as #it
print #it.tbox, "No hands!"
end sub
NOTE: Branch labels inside functions and subroutines are not visible to code outside those functions and subroutines. If code in the main program tries to access a branch label inside a function or subroutine, this will cause get an error. Likewise, functions and subroutines cannot use branch labels defined outside their scope.
Passing Arguments into Subroutines and Fuctions - by value and BYREF |
Through Liberty BASIC 3, values can only be passed into a user subroutine or function by value. "Passing by value" is a common term meaning that once a value is passed into a subroutine or function, it is just a copy of the passed value and has no relationship to the original value. If the value is changed in the called subroutine or function, it does not change in the main program.
Now Liberty BASIC 4 allows us to pass variables by reference. This means that if a subroutine or function so declares, it can modify the value of a variable passed in, and when the subroutine or function ends and execution returns to the caller the change will be reflected in the variable that was used as a parameter in the call.
By default and without any direct instruction by the programmer, parameters passed into user defined functions and subroutines in QBasic and Visual Basic are passed by reference. That is not true in Liberty BASIC, where values are passed by value as the default. Passing by reference is only done when the BYREF keyword is used.
Example of passing by value
This example shows how passing by value works. The only value that comes back from the function is the one assigned to result$ when the function call returns.
'this is the way it always worked
x = 5.3
y = 7.2
result$ = formatAndTruncateXandY$(x, y)
print "x = "; x
print "y = "; y
print result$
end
function formatAndTruncateXandY$(a, b)
a = int(a)
b = int(b)
formatAndTruncateXandY$ = str$(a)+", "+str$(b)
end function
Example of passing by reference
In contrast to the "passing by value" example, each of the parameters in the function in this example are to be byref (pass by reference). This means that when the value of a and b are changed in the function that the variables used to make the call (x and y) will also be changed to reflect a and b when the function returns. Try stepping through this example in the debugger.
'now you can pass by reference
x = 5.3
y = 7.2
result$ = formatAndTruncateXandY$(x, y)
print "x = "; x
print "y = "; y
print result$
'and it works with subroutines too
wizard$ = "gandalf"
call capitalize wizard$
print wizard$
end
function formatAndTruncateXandY$(byref a, byref b)
a = int(a)
b = int(b)
formatAndTruncateXandY$ = str$(a)+", "+str$(b)
end function
sub capitalize byref word$
word$ = upper$(left$(word$, 1))+mid$(word$, 2)
end sub
More about pass by reference
Passing by reference is only supported using string and numeric variables as parameters. You can pass a numeric or string literal, or a computed number or string, or even a value from an array, but the values will not come back from the call in any of these cases. Step through the example in the debugger to see how it works!
'you can also call without variables, but the changes
'don't come back
result$ = formatAndTruncateXandY$(7.2, 5.3)
print result$
'and it works with subroutines too
call capitalize "gandalf"
a$(0) = "snoopy"
call capitalize a$(0)
end
function formatAndTruncateXandY$(byref a, byref b)
a = int(a)
b = int(b)
formatAndTruncateXandY$ = str$(a)+", "+str$(b)
end function
sub capitalize byref word$
word$ = upper$(left$(word$, 1))+mid$(word$, 2)
end sub
Copyright (C) 2003 Shoptalk Systems
Liberty BASIC - http://www.libertybasic.com/