Function parameters
Functions can take parameters, to specialize their behavior.
Purpose of function parameters
The function declaration specifies the name of the function and the identifiers of its formal arguments (if any).
Function parameters hold values passed by the caller, to be used in the body of the function.
Function parameter specification with legacy syntax
DEFINE
statement that immediately follows the argument
list.FUNCTION check_address(zipcode, street, city)
DEFINE zipcode CHAR(5),
street VARCHAR(100),
city VARCHAR(50)
DEFINE found BOOLEAN -- local function variable
...
END FUNCTION
Function parameter specification with fully-typed syntax
FUNCTION check_address(zipcode CHAR(5), street VARCHAR(100), city VARCHAR(50))
DEFINE found BOOLEAN -- local function variable
...
END FUNCTION
Function without parameters
FUNCTION begin_work()
...
END FUNCTION
Passing primitive type values as parameters
Function arguments using simple data types such as INTEGER
are passed by value (the values are copied on the stack).
In the following code example, the variable x
defined in the
MAIN
block will not be modified by the function:
MAIN
DEFINE x INTEGER
LET x = 123
CALL myfunc(x)
DISPLAY x -- displays 123
END MAIN
FUNCTION myfunc(x)
DEFINE x INTEGER
LET x = x + 1
END FUNCTION
Parameters of type TEXT
and BYTE
are also passed by value, but it's
only the large object handler which is copied on the stack. The actual data is pointed to by the
handler and therefore it is not copied.
Type conversions
The actual argument in a call to the function need not be of the declared data type of the formal argument. The runtime system will do the appropriate data type conversions when needed. If the data type conversion is not possible, a runtime error occurs.
NULL
INTEGER
:MAIN
CALL add("aaaaa")
END MAIN
FUNCTION add(x)
DEFINE x INTEGER
DISPLAY "x = ", x
END FUNCTION
Passing complex objects as parameters
MAIN
DEFINE ch base.Channel
LET ch = base.Channel.create()
CALL ch.openFile(arg_val(1), "r")
CALL read_lines(ch)
END MAIN
FUNCTION read_lines(ch base.Channel)
DEFINE s STRING
WHILE TRUE
LET s = ch.readLine()
IF ch.isEOF() THEN EXIT WHILE END IF
DISPLAY s
END WHILE
END FUNCTION
Passing records as parameters
.*
(dot star) notation, records are expanded on the stack: Each field of the record is passed by value like a
primitive data type. This is supported for backward
compatibility:CALL show_cust_info( r_cust.* )
.*
notation as a single
structured value. The record is still copied on the stask (the record of the caller cannot by
modified by the
function):SCHEMA stores
TYPE t_cust RECORD LIKE customer.*
FUNCTION insert_cust(r t_cust) RETURNS ()
INSERT INTO customers VALUES (r.*)
END FUNCTION
INOUT
keyword in
the function
definition:SCHEMA stores
TYPE t_cust RECORD LIKE customer.*
FUNCTION init_cust(r t_cust INOUT) RETURNS ()
LET r.cust_id = 0
LET r.cust_name = "<undefined>"
LET r.cust_addr = "<undefined>"
LET r.cust_crea = CURRENT
END FUNCTION
Passing records by reference with INOUT
is only supported
when the called function is defined locally, or is known by the compiler because it was imported
with IMPORT FGL
.
For more details, see Passing records as parameter.