![]() |
<< Index >> |
FutureBasic 5 |
local fn | statement | |
|
[clear] local fn functionName [(arg1 [,arg2 ...])]
[statementBlock]
end fn [= expr]
end fn
statement. A local function is a named collection of statements which can be accessed and executed as a unit by referring to the function's name (see the fn <userFunction> statement). All variables and arrays referenced in a local function (except those explicitly declared as "global") are local to the function, which means they do not have any influence outside of the function; any identically-named variables which appear outside of the function are actually different variables, and occupy a different place in memory, than the function's local variables. (An exception to this rule occurs when an array is listed as one of the function's formal parameters; see more about this below.) When your program "calls" (executes) a local function, you can pass data into the function by means of its parameter list (also called its argument list), and you can receive a value back from the function by means of its return value. Local functions allow you to encapsulate complex programming tasks; they're a fundamental and extremely powerful programming construct.local fn
statement also declares the function's name, the data type of its return value (if any), and the number and types of its input parameters (if any). A local function can be placed anywhere in the program, except inside another local function; you should also not place a local function inside a "block" structure such as long if...end if
, etc. The statements in statementBlock
can contain anything except the following:local
statement;
clear
keyword causes all of the function's local variables and arrays (except the parameter variables arg1
, arg2
etc.) to be initialized to zeros, null strings or empty records, each time the function is called. Otherwise, the local variables and arrays will have unpredictable initial values. (You can accomplish the same effect by using the local
statement with the clear
keyword; see the local
statement for more information.)functionName
must be unique; that is, it must be different from the name used in any other local fn
, def fn using
statement anywhere else in the program. If the function is to return a value, then you should specify the data type of the return value by including an appropriate type-identifier suffix at the end of functionName
. For example, a local function which is to return a string value might be declared as follows: local fn FullName$(idNum&)
&
" type-identifier suffix or omit it. No type-identifier suffix should be appended to functionName
if the function does not return a value.statementBlock
, your program must "call" the function using the fn <userFunction>
statement. The fn <userFunction>
statement can appear anywhere in your program, as long as the function it calls is either defined (using the local fn
statement) or prototyped (using the def fn <prototype>
statement) somewhere above the fn <userFunction>
statement. This restriction is required in order to allow your program to compile; however, the actual order of execution of your program's statements is not affected by where you place your local fn
's.arg1
, arg2
etc. can have any of the following forms:Parameter form | Description |
SimpleVar | A simple numeric or string variable. Cannot be a record variable, a record field nor an array element. |
ptrVar As Pointer [To unType] | (See below.) |
@longVar& | longVar& is a simple long-integer variable. |
@ptrVar As Pointer [To unType] | (See below.) |
tableau(dim1[,dim2...]) | array is a numeric or string array (not an array of records), and dim1, |
local fn
statement are called the function's "formal arguments." They must not be global variables. You should not declare the formal argument variables in a dim
statement; they are implicitly declared by the local fn
statement.fn <userFunction>
statement are called the "actual arguments." They must match the function's formal arguments in number, and they must be of "compatible types" (see fn <userFunction>
for more information). Each time the function is called, values are assigned to its formal arguments as follows:ptrVar as pointer [to someType]
, then the actual argument should be either a record variable or a long-integer expression. In the first case, the record's address is copied into ptrVar; in the second case, the long integer's value is copied into ptrVar
.
@longVar&
, or @ptrVar as pointer [to someType]
, then the actual argument must either be a variable (possibly a record variable), or a long integer expression preceded by "=". In the first case, the variable's address is copied into longVar&
or ptrVar
. In the second case, the value of the long integer expression is copied into longVar&
or ptrVar
.
array(dim1 [,dim2 ...])
, then the actual argument must be the base element of an array of the same type, which has the same number of dimensions. The base element is the element in which all subscripts are set to zero. The entire array is then accessible to the local function, and (important!) any changes made to the array's elements within the function will persist after the function exits.
functionName
.local fn
statement. For example, suppose we have a function defined like this:local fn SetElements(anArray&(1,7), max&)
'Set each element to 1492 in the array:
for i& = 0 to max&
for j = 0 to 7
anArray&(i&,j) = 1492
next
next
end fn
fn SetElements
, the passed array can have any size as its first declared dimension, as long as it has a second dimension declared as 7. For example:dim arrayOne&(1250,7), arrayTwo&(465,7)
fn SetElements(arrayOne&(0,0), 1250)
fn SetElements(arrayTwo&(0,0), 465)
fn SetElements
, we can set the first subscript in anArray&
to values much greater than 1, even though anArray&
was "declared" with dimensions (1,7).local fn
statement) and the external dim
statement that declares the actual passed array.expr
in the end fn
statement, the function will "return" the value of expr
. This can be any expression which is compatible with the type-identifier suffix (if any) that appears in functionName
. When your function "returns" a value, it means that you can reference the function (using fn <userFunction>
) as part of a string or numeric expression, and the function's return value will be substituted in the expression. For example: maxPuppets = 6 * fn storeCount%(x)
fn storeCount%(x)
returns a value of 7, then the value 42 will be assigned to maxPuppets
.end fn
statement is executed. Therefore, you should never make reference to a local variable's address after the function has finished executing; in particular, you should never pass a local variable's address back to the routine that called the function. For example:'DON'T do THIS!
local fn myFunction&(x,y,z)
dim r#
r# = sqr(x*x + y*y + z*z)
end fn = @r#
rAddr& = fn myFunction&(x,y,z)
rAddr&
points to an area of memory (the old address of r#
) which is no longer reserved, and which should not be used.'THIS IS OKAY:
local fn FirstFn
dim as str255 myPascalString
'Pass address of local var into another fn:
fn SecondFN(@myPascalString)
end fn
:
local fn SecondFn(strAddr&)
BlockMove @gPascalString, strAddr&, len(gPascalString)+1
end fn
FNpermute_r
calls itself. It would be very difficult to write such a program without using recursive functions.'Function prototypes:
def fn Permute(aPascalString)
def fn permute_r(prefixPascalString, suffixPascalString)
input "Enter a word: "; theWordPascalString
fn Permute(theWordPascalString)
end
local fn Permute(aPascalString)
'Prints all permutations of the letters in aPascalString
fn permute_r("", aPascalString)
end fn
local fn permute_r(prefixPascalString, suffixPascalString)
'Prints all permutations of prefixPascalString+suffixPascalString
'that start with prefixPascalString
long if suffixPascalString = ""
print prefixPascalString
xelse
for i = 1 to len(suffixPascalString)
'Move the i-th letter of suffixPascalString over to newprefixPascalString:
newprefixPascalString = prefixPascalString + mid$(suffixPascalString, i, 1)
newsuffixPascalString = left$(suffixPascalString,i-1) + mid$(suffixPascalString,i+1)
'Now print all permutations that
'start with newprefixPascalString
fn permute_r(newprefixPascalString, newsuffixPascalString)
next
end if
end fn
end fn
statement can return only a single numeric or string expression. But many times, it's useful to have a local function which can return more than one value. The way to accomplish this is through the function's parameter list. If you give the function access to the address of some external variable or array, then the function can alter the contents at that address, effectively modifying the value of that variable or array.array(dim1 [,dim2 ...]
) syntax in the formal parameter list), then your function implicitly has access to the address of the passed array. Any changes you make to the array's elements inside your function are actually made to the external array, so the changes persist after the function exits.
@var
syntax in the function's formal parameter list, and specify a variable when you call the function, then the variable's address is copied into var. Your function can then modify the contents at that address.
pointer
formal parameter.