Using functions in programs

The FUNCTION block defines the body and the signature (i.e. declaration) of a function. The function declaration specifies the name of the function and the identifiers of its formal arguments (if any).

Function names, like other identifiers are case-insensitive. If the function name is also the name of a built-in function, an error occurs at link time, even if the program does not reference the built-in function.

A FUNCTION block cannot appear within the MAIN block, in a REPORT block, or within another FUNCTION block.

A function can be invoked with the CALL statement, it can be used in an expression when returning a unique value, or it can be invoked automatically when registered by a callback mechanism like WHENEVER ERROR CALL.

If no argument is needed in a function call, an empty argument list must still be supplied, enclosed between the parentheses.

By default, functions are public; They can be called by any other module of the program. If a function is only used by the current module, you may want to hide that function to other modules, to make sure that it will not be called by mistake. To keep a function local to the module, add the PRIVATE keyword before the function header. Private functions are only hidden to external modules, all function of the current module can still call local private functions.
PRIVATE FUNCTION check_number(n)
  ...
END FUNCTION
The data type of each formal argument of the function must be specified by a DEFINE statement that immediately follows the argument list. The actual argument in a call to the function need not be of the declared data type of the formal argument. If data type conversion is not possible, a runtime error occurs.
FUNCTION check_address(zipcode, street, city)
  DEFINE zipcode CHAR(5),
         street VARCHAR(100),
         city VARCHAR(50)
  ...
END FUNCTION
Function arguments are passed by value (i.e. value is copied on the stack) for basic data types and records, while dynamic arrays and objects are passed by reference (i.e. a handle to the original data is copied on the stack and thus allows modification of the original data inside the function).
-- The following code is useless:
-- Variable x will not be modified by the function
MAIN
  DEFINE x INTEGER
  LET x = 123
  CALL increment(x)
  DISPLAY x   -- displays 123
END MAIN

FUNCTION increment(x)
  DEFINE x INTEGER
  LET x = x + 1
END FUNCTION
Local variables are not visible in other program blocks. The identifiers of local variables must be unique among the variables that are declared in the same FUNCTION definition. Any global or module variable that has the same identifier as a local variable, however, is not visible within the scope of the local variable.
DEFINE x INTEGER   -- Declares a module variable

FUNCTION func_a()
  DEFINE x INTEGER -- Declares a local variable
  LET x = 123      -- Assigns local variable
END FUNCTION

FUNCTION func_b()
  LET x = 123     -- Changes the module variable
END FUNCTION
A function that returns one or more values to the calling routine must include the return-statement . Values specified in RETURN must correspond in number and position, and must be of the same or of compatible data types , to the variables in the RETURNING clause of the CALL statement. If the function returns a single value, it can be invoked as an operand within a expression. Otherwise, you must invoke it with the CALL statement with a RETURNING clause. An error results if the list of returned values in the RETURN statement conflicts in number or in data type with the RETURNING clause of the CALL statement that invokes the function.
MAIN
  DEFINE zipcode CHAR(5),
         street VARCHAR(100),
         city VARCHAR(50)
  CALL get_address() RETURNING zipcode, street, city
END MAIN

FUNCTION get_address()
   ...
   RETURN "23500", "461 Ocean blvd", "Kreistone"
END FUNCTION

A function can invoke itself recursively with a CALL statement. This will result in a recursive call.