|
<< Click to Display Table of Contents >> FUNCTION |
![]() ![]()
|
FUNCTION is used to define user-defined functions. Such user functions may return a variable (if you need to return multiple variables, consider returning a map). For a function that does not return anything (a stand-alone function), you may consider using a procedure instead (a procedure is essentially the same as a user function with no return value).
Note that all Gekko functions (both in-built and user-defined) implement so-called UFCS so that a function like for instance f(x, y) can be written as x.f(y), and f(x, y, z) can be written as x.f(y, z).
Libraries It is possible to organize user-defined functions and procedures in libraries. These are basically just .zip-files that are loaded with the LIBRARY statement. |
You may decorate a user function with a <>-option field containing an optional time period. User-defined functions allow optional parameters with default values, and the function may prompt (ask) the user about these parameters, if f?(...) is used instead of f(...), where f is the name of the function. See the LOCAL keyword if you need variables defined inside the function to be inaccessible/nonexisting outside the function.
function type funcname(<date t1, date t2>, type1 var1 label1 = default1, type2 var2 label2 = default2, ...);
expressions... ;
end;
Unless the return type is void, the function body must contain at least one RETURN statement, returning a variable.
t1, t2 |
(Optional). You may state optional time period parameters inside <>-brackets, for instance function series f(<date %t1, date %t2>, series x); after which %t1 and %t2 are assigned to for instance 2020 and 2030 in the call f(<2020 2030>, z). If the function is called without <>-brackets, for instance f(z) , the parameters %t1 and %t2 are assigned to the local/global time period instead. Using a <>-brackets in a function call does not in itself change the local time period inside the function: use for instance the BLOCK structure to do that. See examples. |
type1, ... |
Types of incoming and outgoing variables: series, val, date, string, list, map, matrix. You may also use the special name type for parameters, which behaves 100% as a string inside the function, but where the single quotes are omitted when calling the function from outside (the shorter call f(y) is used instead of f('y')).
If the function does not return anything, void can be used as type. |
var1, ... |
The parameters/variables/expressions |
label1, ... |
(Optional). A label for the parameter, used if the function is promting (called with f?(...)). See more about prompting below. |
default1, ... |
(Optional). A default value for the parameter. If the parameter is omitted, the default value is used. If the function is asked to prompt (called with f?(...)) and the parameter is omitted, the default value is shown in the dialog box. In the dialog box, Enter or Escape will return the default value, and fire up the next dialog box (for the next optional parameter). If a ; is entered in the dialog box, all the remaining parameters attain their default values, and no more dialog boxes are shown. For string input, the use of quotes (') in the input box is optional. At the moment, only val, date and string types can be used for prompting input boxes. |
funcname |
The function name |
body |
The function body, that is, the statements to be performed. Use RETURN to return a variable. If several variables need to be returned, use a map or list to bundle them. |
Tip: if you need to stop execution at a specific point/line to inspect variables etc., try inserting a STOP statement. This will abort from all called program files/procedures/functions, without executing anything more after the STOP (this is not the case regarding RETURN). Therefore, STOP can be practical for debugging, etc.
Value examples, including multiple return values
The function sq() below returns the input value squared.
function val sq(val %x); |
The example will produce %y = 16 and %z = 256 (the function calls may be nested).
Multiple variables may be returned, using a collection like for instance a map:
function map f(val %x, val %y); |
Date example
function date add3(date %d); |
String example
function string f(string %x); |
If you prefer to omit the quotes when calling the function (that is, f(sun) instead of f('sun'), you may use the name type:
function string f(name %x); |
List example
function val ncommon(list #x, list #y); |
Series example
function series idx(series x, date %d); |
The function idx() provides indexed values.
Stand-alone function call example (void type)
function void f(val %x1, val %x2, val %x3); // like "f 1 -2 3;" but without the // problem of this being interpreted as // "f (1-2) 3;", or "f -1 3;". |
Combined example
function void load(string %n, string %label, date %d1, date %d2, val %v); |
The load() function will create the two timeseries extra1 and vat, both with labels, and values 100 and 0.25, respectively. Since the function does not return any variable, you may use a procedure instead.
Local period example
function series f(<date %t1, date %t2>); |
In the z1 statement, it is seen how the local period <2002 2002> is used inside the f() function, by means of a BLOCK using the arguments %t1 and %t2. The f() function itself is not called with time period, and since the time period is absent in the function call, %t1 and %t2 are assigned to the local period set outside of the f() function.
The z2 statement illustrates a call of f() where a time period is present inside the f() function. This overrules the local time period 2002-2002.
Promt and default values example
Gekko user-defined functions allow default values, and prompting regarding these.
function val f(val %x1, val %x2 'parameter 2' = 1, val %x3 'parameter 3' = 2); |
Beware that f() or f?() will fail with an error, since the first parameter is required. As shown regarding the last function call, you may terminate a sequence of input boxes with ;, which means the default values are used for the current and following parameters. Pressing Enter or Escape returns the default value, and opens up the next input box. For prompt input, only the variable types val, date, string and name are supported at the moment (for name type, use for instance ... , name %x2 'parameter 2' = 'x', ...).
See also PROCEDURE. A procedure can be thought of as a function without return values. Procedures and user functions do not live in databanks, and are hence not affected by CLEAR, CLOSE, READ, etc., but are removed with RESTART or RESET.
If a function is defined without <>-brackets to indicate time, it may still be called with <>-brackets. In that case, the time period inside the brackets is just ignored. Note that multiple return values can be handled with maps.
You may at most use 14 arguments, else use maps to bundle incoming arguments. Per default, all arguments are passed by value, not by reference (cf. option system clone). This means that functions cannot have so-called side-effects on the incoming arguments. Maps can be practical for bundling output variables.
It is planned to introduce the type namelist in addition to the name type, so that an argument like (a, b, c) can mean ('a', 'b', 'c') internally.
LIBRARY, LOCAL, PROCEDURE, RUN