User-defined functions

User-defined functions (FN) work like the built-in functions — ABS(n), MOD(a,b), LEFT$(a$,n), and so on — except that the user defines what the function does. Defining new FN functions is something like extending the definition of the BASIC language. The FN function contains code that can be called from several places in the program, each time returning to the place from which it was called on that occasion. (The GOSUB is another way to write code to be called from multiple places.)

Here is an example of a user-defined function that takes a single numeric parameter and simply returns a numeric value that is twice the value: FN.DEF Double(A) FN.RTN A*2 FN.END

Location. An FN function must be defined earlier in the program than any of the places that call it. Generally, a program consists of all the FN functions, followed by the main program.

Nesting/recursion. An FN function can call another FN function, and can even call itself (directly or through intermediate functions). Be sure that, when an FN function calls itself, you take care that the process does not repeat indefinitely. Each call requires memory from the execution stack, which is part of the memory that Android allocates to your program; making function calls without limit will eventually make the program fail for lack of memory.

Return value. Every FN function returns a numeric or string value, which can be used as though the value replaced that use of the FN function. For example, you can code an FN function instead of a value supplied to a BASIC statement, in order to use a computed rather than a constant value. You can assign the return value to a variable. You can use an FN function in an expression, to combine the return value with other quantities. Continuing the above example that defined a function, this code prints the value of 2E + 5: PRINT Double(E)+5

You can use the name of an FN function as a BASIC statement of its own. In that case, the function's defined behavior is executed but its return value is not used. In such cases where the return value is unimportant, you can precede the function with the keyword. The following would compute the value 24 but do nothing with it. CALL Double(12)

Name. When defining an FN function, you specify its name. The rules for naming FN functions are the same as for naming variables. If the function's return value will be a string, its name must end in $. Otherwise, the return value will be numeric.

The formatter capitalizes the names of built-in functions, but does not capitalize the names of user-defined functions. Use of lowercase letters is an easy way to indicate that a function is user-defined with FN.

The name can be the same as a built-in function. For example, you are free to provide your own definition of MOD. In this case, your MOD is called instead of the built-in MOD, and there is no way to gain access to the built-in function.

A single program must not define the same FN function more than once.

Parameters
Parameters let an FN function communicate with the code that calls it. Each parameter is one of the following
 * 1) A numeric scalar, such as
 * 2) A string scalar, such as
 * 3) A numeric array, such as
 * 4) A string array, such as

The parameters in the function definition correspond to the parameters in each location that calls the function, by their sequence inside the parentheses. The type of parameter in each call must be the type that the function expects. For instance, if the 2nd parameter in the function's definition is a numeric scalar, then in every call to that function, the 2nd parameter must be a numeric scalar (which can be a constant or an expression).

Parameters let the caller pass values to the function. Parameters let the function pass values back to the caller only in the following cases:
 * The parameter is an array, or
 * The caller passes the name of a scalar variable and precedes it with the symbol.

In these two cases, the function can change the variable and the caller will receive the changed value in the scalar variable that it passed to the function. (In these cases, parameters are "passed by reference" rather than "passed by value.") The return value is another method for a function to pass a value back to the caller.

If a function has no parameters, the parentheses must be present, both when defining and when calling the function.

Variable scope
With two exceptions noted below, all variables a user-defined function creates are private to it. If you write an FN function that creates a variable V$, then this variable: That is, the scope of a variable in an FN function is that single call to that single function. When the function returns, all its variables are discarded and the memory they used is reclaimed.
 * Is unrelated to any V$ defined outside the function, and
 * Is unrelated to V$ during any previous call to the same function.

If your FN function creates a variable V$ and calls itself, then the inner function cannot obtain or modify the V$ value set by the outer one. If the inner function creates a variable V$, it will be a new, independent variable.

BASIC data structures that programs use with a numeric pointer — such as lists, stacks, bundles, bitmaps, and graphical objects — are global to the BASIC program. If an FN function executes, then P survives only until the function returns. But bundle number 4 is the same as it is throughout the BASIC program. So FN functions can read and modify all these data structures.
 * Data structures

A BASIC interrupt routine has access to the global symbol table and, if it calls an FN function, that function also has access to variables defined outside it. This is an exception to the general rule, and is a source of programming errors that are difficult to locate. If you define a function that creates a variable I, then if called from an interrupt routine, creating that variable might change the value of a variable named I that had been created in the mainline.
 * Interrupt routines

FN.DEF
Defines a user-defined function

FN.DEF name|name$( {nvar}|{svar}|array[]|array$[], ... )
 * Synopsis

FN.DEF begins the definition of a function.
 * Description

Following FN.DEF is the desired name of the function. If the return value will be a string, then give the function a string name, by appending. If the return value will be numeric, omit the.

If the function takes parameters, list the names by which they will be known within the function, surrounded by parentheses and separated by commas. Each parameter can be numeric or string; it can be a scalar (single value) or an array.

FN.DEF cut$(a$, left, right) FN.DEF sum(a, b, c, d, e, f, g, h, i, j) FN.DEF sort(v$[], direction) FN.DEF pi
 * Examples

FN.RTN
Returns from a user-defined function

FN.RTN |
 * Synopsis

FN.RTN specifies the return value (see the introduction) that the function returns to its caller. If FN.DEF defined a string function (if the function's name ended in ), then FN.RTN must be followed by an sexp.  If FN.DEF defined a numeric function, then FN.RTN must be followed by an nexp.  FN.RTN must provide a return value; the caller does not have to do anything with it. (See, for example, CALL.)
 * Description

Parameters passed by reference are another way for a function to return data to its caller.

A function cannot return a data structure, such as a bundle, but it can return a number meant to be used as the pointer of a bundle.

As well as indicating the return value, FN.RTN performs an immediate transfer of control to the caller. There can be as many FN.RTN statements as desired inside a function (such as in an IF statement) and no code following FN.RTN is reached on that call to the function.

The following function is comparable to the built-in MAX function: FN.DEF Bigger(A,B) IF A > B THEN FN.RTN A FN.RTN B FN.END
 * Example

The immediate return of FN.RTN to the caller means there is no need to use the keyword ELSE.

CALL
Calls a user-defined function but discards its return value

CALL 
 * Synopsis

The CALL statement calls a user-defined function. If the function returns a value, it is not used; to use a return value, do not use CALL but just include the function call in an expression or BASIC statement.
 * Description

Like LET, the keyword CALL can be omitted. This leads to slightly faster execution. However, you must use CALL if the start of the name of the function is the same as a BASIC keyword. For example, the  function might modify its parameter but not return a useful value. You could call it like this: CALL Format(&A$)

However, omitting the keyword CALL would make the interpreter read this function name as the start of a FOR statement.