The CALL instruction invokes a specified function or method.
CALL [ prefix. ] function ( [ parameter [,...] ] ) [ RETURNING variable [,...] ]
The CALL instruction invokes the function or class/object method specified and passes the program flow control to that function/method. After the called function was executed, the flow control goes back to the caller, the runtime system executing the next statement that appears after the CALL instruction.
Function arguments can be any expression supported by the language. Use a double-pipe operator || to pass the concatenation of character string expressions as a parameter.
CALL my_function( TODAY, 20*0.5435, 'abc'||'def'||var1 )
The RETURNING clause assigns values returned by the function to variables in the calling routine. The RETURNING clause is only needed when the function returns parameters.
MAIN DEFINE var1 CHAR(15) DEFINE var2 CHAR(15) CALL foo() RETURNING var1, var2 DISPLAY var1, var2 END MAIN FUNCTION foo() DEFINE r1 CHAR(15) DEFINE r2 CHAR(15) LET r1 = "return value 1" LET r2 = "return value 2" RETURN r1, r2 END FUNCTION
If the function returns a unique parameter, the function can be used in an expression and can be directly assigned to a variable with LET var = function(...) statement.
MAIN DEFINE var1 CHAR(10) DEFINE var2 CHAR(2) LET var1 = foo() DISPLAY "var1 = " || var1 CALL foo() RETURNING var2 DISPLAY "var2 = " || var2 END MAIN FUNCTION foo() RETURN "Hello" END FUNCTION
The value of a receiving variable may be different from the value returned by the function, following the data conversion rules.
MAIN DEFINE s STRING LET s = div(10,2) END MAIN FUNCTION div(x,y) DEFINE x,y INTEGER RETURN x / y END FUNCTION
Records can be passed to and returned from functions, but the record structure must be flat and each member is passed or returned individually by value. Records are not passed by reference.
MAIN DEFINE r RECORD x INT, y INT, z INT END RECORD CALL foo(r.*) RETURNING r.* DISPLAY r.* END MAIN FUNCTION foo(x,y,z) DEFINE x,y,z INT RETURN z,y,x END FUNCTION
If the IMPORT FGL instruction was used to import a module, function can be prefixed with the name of the module followed by a dot (i.e. module.function). The module prefix is required to fully-qualify the function in case of conflicts (i.e. when functions with the same name are defined in several modules).
-- main.4gl IMPORT FGL module1 IMPORT FGL module2 MAIN CALL module1.show("aaa") CALL module2.show("aaa") END MAIN
-- module1.4gl FUNCTION show(s) DEFINE s STRING DISPLAY s END FUNCTION
-- module2.4gl FUNCTION show(s) DEFINE s STRING DISPLAY s END FUNCTION