As shown in chapter 1 (in section 1.6.), a libfawk script normally consists of multiple functions. Function naming has the same rules as variable naming (see chapter 2). A function needs to have a name that is unique within the script.
The order of functions in the script does not matter: code can call functions that are not yet defined. There is no need for forward declarating functions.
Every function has a return value. There are two ways for returning from a function:
The syntax for return is one of these:
return expr return
The first variant evaluates expr and the return value of the function will be the result of the evaluation. The second variant returns NIL. The function immediately stops executing and returns when a return statement is hit.
The function will return NIL when executing the implicit return
For example the following function pi() returns the value of pi and
main() will print it:
A function may list zero or more parameters in its definition in
the parenthesis. Parameters are identified by their names:
In this example bar and baz are function parameters to foo(). Within
foo() any reference to bar and baz will access the function parameter.
If there was a global variable on the same name, it is unaccessible
from foo(), because the parameter on the same name shadows the
global variable.
Scalar values are passed by copy. That means at the time of the call,
the caller supplied values are copied into new memory locations designated
for the parameters of the call instance. If the function changes
a the value of parameter, that affects only this copy, not the original
version at the caller:
Note: arrays are passed by reference and are not copied. See chapter 5.
This is all true when a libfawk script calling a libfawk script function.
When a libfawk script calling a C function there is an extra case: if the function
parameter is a variable prefixed with & on the caller side, a reference
is passed - example is delete(&var) where we want delete() to get the
variable itself, not the value of the variable.
The caller usually supplies exactly as many parameters as the
function was defined with. The caller must not supply more
parameters than the function has. But the caller may supply less
parameters, in which case the parameters that are not supplied by
the caller are initialized to NIL on function entry:
In this example only a and b of foo() are passed by the caller. c is
still a parameter, which means it is not a global variable. Then foo()
uses c as a temporary variable for calculating the result. Parameters
defined but not passed are automatically initialized to have the NIL value.
This usage of parameter c is called a "local variable". As a convention
it is recommended to add a few spaces between the parameters that are expected
from the caller and the parameters intended for local variables in the
function definition (for code clarity).
Another use of the same mechanism is having optional parameters
that the caller may or may not fill in:
Function scale detects if factor is passed by looking at its
value: if it is NIL, it is not passed so it picks the default value of
5.
It is possible to save a function reference in a variable and call
the function using the variable:
Note: the difference between retrieving the function reference and calling
the function is the paranthesis: if there is parentesis opening after the
name of the function, it is a function call. If there is no parenthesis,
just the function name, it is then a reference to the function.
This syntax is similar to function call vs. function address in C.
Some functions may need to take a variable number of arguments and decide
how to process them runtime. Libfawk provides VARARG[] support for this.
Place the special argument name ... in the function's argument list
and it will be turned into a local array called VARARG[] that eats up all
remaining caller arguments, indexed from 0 up:
After the call, in foo(), a is "p1", b is 5, VARARG[] is [0]=10, [1]=20,
[2]="p2" and n is NIL.
The ... argument splits the argument list so it has three sections:
4.3. Function parameters
function foo(bar, baz)
{
return bar+baz;
}
function foo(bar, baz)
foo = bar+baz;
end function
function foo(bar, baz)
begin
foo := bar+baz;
end;
4.4. Excess parameters: local variables
4.5. Excess parameters: optional parameters
4.6. Function references
4.7. Variable argument function