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 FUNCTIONFunction 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 FUNCTIONFunction without parameters
FUNCTION begin_work()
   ...
END FUNCTIONPassing 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 FUNCTIONPassing 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 FUNCTIONPassing 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 FUNCTIONINOUT 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 FUNCTIONPassing 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.