| function-name |
(<[([prototype-clause] [intermediate-result-clause])]
|
[parameter] [,[parameter]] ...>) |
| [array-index-expression] |
For an explanation of the symbols used in the syntax diagram, see Syntax Symbols.
Related Statements: DEFINE
PROTOTYPE | DEFINE
FUNCTION
This document covers the following topics:
A function call invokes a Natural object of the type function.
A function is defined with the DEFINE
FUNCTION statement which contains the parameters, local and
application-independent variables, the result value to be used and the statements to be
executed when the function is called.
A function is called by specifying either of the following:
the function name as defined in the DEFINE
FUNCTION statement, or
an alphanumeric variable that contains the name of the function at execution time.
In this case, it is necessary to reference the variable in a DEFINE PROTOTYPE statement with
the VARIABLE keyword.
A function call can be used within a Natural statement instead of a read-only operand. In this case, the function has to return a result which is then processed by the statement like a field containing the same value.
It is also possible to use a function call in place of a Natural statement. In this case, the function need not return a result value; if returned, the value result is discarded.
Function calls are not allowed in the following situations:
in positions where the operand value is changed by the Natural statement, for example:
MOVE 1 TO #FCT(<..>);
in a DEFINE DATA
statement;
in a database access statement, such as READ, FIND, SELECT, UPDATE and STORE;
as an argument of Natural system functions, such as AVER, SUM and *TRIM;
in an array index expression;
as a parameter of a function call.
If a function call is used in an INPUT statement, the return value will be treated like a
constant value. This leads to an automatic assignment of the attribute AD=O to make this field write-protected (for output only).
Operand Definition Table:
| Operand | Possible Structure | Possible Formats | Referencing Permitted | Dynamic Definition | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
function-name
|
S | A | A | U | yes | no | |||||||||||||
Syntax Element Description:
| Syntax Element | Description |
|---|---|
function-name
|
Function Name:
|
prototype-clause |
Prototype Clause:
|
intermediate-result-clause |
Intermediate Result Clause:
|
parameter |
Parameter Specification:
See |
array-index-expression |
Array Index Notation:
If the result returned by the function call is an array, an index notation must be provided to address the demanded array occurrences. For details, refer to Index Notation in User-Defined Variables. |
PT=
prototype-name |
Natural requires parameter definitions and the function result to resolve a function
call at compile time. If no prototype matches function-name, the parameters
or the function result defined for the called function, you can assign a matching
prototype with the prototype-clause. In this
case, the referenced prototype steps in place and is used to resolve the parameter and
function result definitions. The function-name declared in the
referenced prototype is ignored.
Syntax Element Description:
| Syntax Element | Description |
|---|---|
prototype-name |
Prototype Name:
|
IR=
|
|
format-length [/array-definition] |
|
||||||
[(array-definition)] HANDLE OF OBJECT |
|||||||||
| ( |
|
|
[/array-definition]) DYNAMIC
|
||||||
This clause can be used to specify the
format-length/array
definition of the result value for a function call if neither
the cataloged object of the function nor a prototype definition is available. If a
prototype is available for this function call or if a cataloged object of the called
function exists, the result value format specified with the
intermediate-result-clause is checked for
data transfer compatibility.
Syntax Element Description:
| Syntax Element | Description |
|---|---|
format-length |
Format/Length Definition:
The format and length of the field. For information on the format/length definition of user-defined variables; see Format and Length of User-Defined Variables. |
array-definition |
Array Dimension Definition:
With an array-definition, you define the lower and upper bounds of the dimensions in an array definition. See Array Dimension Definition in the Statements documentation. |
HANDLE OF OBJECT |
Handle of Object:
Used in conjunction with NaturalX. For further information, see NaturalX in the Programming Guide. |
A, B or U |
Data Format:
Possible formats are alphanumeric, binary or Unicode for dynamic variables. |
DYNAMIC |
Dynamic Variable:
A field can be defined as For further information on processing dynamic variables, see Introduction to Dynamic Variables and Fields. |
|
|
nX
|
|
|||||||
|
|
|
|
|
|
|||||
| operand |
(AD=
|
)
|
|||||||
You can specify single or multiple parameters to pass data values to the function. They
can be provided as constant values or variables, depending on the DEFINE DATA PARAMETER definition
within the function.
Multiple parameters must be separated from each other either by a comma or by the
input delimiter character specified with the session parameter ID. If numbers are provided
in the parameter list and a comma is defined as the decimal character (with the
session parameter DC), either separate the comma from the value with
an extra blank character or use the input delimiter character.
Example with ID=; and DC=, delimiter settings: WRITE
F#ADD (<1 , 2>) F#ADD (<1;2>)
The semantic and syntactic rules which apply to the function parameters are the same as
described in the parameters section of subprograms; see Parameters in
the description of the CALLNAT
statement.
Operand Definition Table:
| Operand | Possible Structure | Possible Formats | Referencing Permitted | Dynamic Definition | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
operand
|
C | S | A | G | A | N | P | I | F | B | D | T | L | C | G | O | yes | no | ||
Syntax Element Description:
| Syntax Element | Description | |
|---|---|---|
nX
|
Parameters to be Skipped:
With the notation A parameter that is to be skipped must be defined with the keyword |
|
AD=
|
Attribute Definition:
If |
|
AD=O
|
Non-modifiable:
See session parameter Note |
|
AD=M
|
Modifiable:
See session parameter This is the default setting. |
|
AD=A
|
Input only:
See session parameter |
|
|
Note |
||
The example program FUNCEX01 uses
the functions F#ADDITION, F#CHAR, F#EVEN and F#TEXT.
All example sources shown in this section are provided as source objects and cataloged objects in the Natural SYSEXPG system library.
** Example 'FUNCEX01': Function call (Program)
************************************************************************
DEFINE DATA LOCAL
1 #NUM (I2) INIT <5>
1 #A (I2) INIT <1>
1 #B (I2) INIT <2>
1 #C (I2) INIT <3>
1 #CHAR (A1) INIT <'A'>
END-DEFINE
*
IF #NUM = F#ADDITION(<#A,#B,#C>) /* Function with three parameters.
WRITE 'Sum of #A,#B,#C' #NUM
ELSE
IF #NUM = F#ADDITION(<1X,#B,#C>) /* Function with optional parameters.
WRITE 'Sum of #B,#C' #NUM
END-IF
END-IF
*
DECIDE ON FIRST #CHAR
VALUE F#CHAR (<>)(1) /* Function with result array.
WRITE 'Character A found'
VALUE F#CHAR (<>)(2)
WRITE 'Character B found'
NONE
IGNORE
END-DECIDE
*
IF F#EVEN(<#B>) /* Function with logical result value.
WRITE #B 'is an even number'
END-IF
*
F#TEXT(<'Hello', '*'>) /* Function used as a statement.
*
WRITE F#TEXT(<(IR=A12) 'Good'>) /* Function with intermediate result.
*
END
FUNCEX01Sum of #B,#C 5
Character A found
2 is an even number
*** Hello world ***
Good morning
The function F#ADDITION is defined in the example function
FUNCEX02.
** Example 'FUNCEX02': Function call (Function)
************************************************************************
DEFINE FUNCTION F#ADDITION
RETURNS (I2)
DEFINE DATA PARAMETER
1 #PARM1 (I2) OPTIONAL
1 #PARM2 (I2) OPTIONAL
1 #PARM3 (I2) OPTIONAL
END-DEFINE
/*
RESET F#ADDITION
IF #PARM1 SPECIFIED
F#ADDITION := F#ADDITION + #PARM1
END-IF
IF #PARM2 SPECIFIED
F#ADDITION := F#ADDITION + #PARM2
END-IF
IF #PARM3 SPECIFIED
F#ADDITION := F#ADDITION + #PARM3
END-IF
/*
END-FUNCTION
*
END
The function F#CHAR is defined in the example function
FUNCEX03.
** Example 'FUNCEX03': Function call (Function) ************************************************************************ DEFINE FUNCTION F#CHAR RETURNS (A1/1:2) /* F#CHAR(1) := 'A' F#CHAR(2) := 'B' /* END-FUNCTION * END
The function F#EVEN is defined in the example function
FUNCEX04.
** Example 'FUNCEX04': Function call (Function)
************************************************************************
DEFINE FUNCTION F#EVEN
RETURNS (L)
DEFINE DATA
PARAMETER
1 #NUM (N4) BY VALUE
LOCAL
1 #REST (I2)
END-DEFINE
/*
DIVIDE 2 INTO #NUM REMAINDER #REST
/*
IF #REST = 0
F#EVEN := TRUE
ELSE
F#EVEN := FALSE
END-IF
/*
END-FUNCTION
*
END
The function F#TEXT is defined in the example function
FUNCEX05 in library SYSEXPG.
** Example 'FUNCEX05': Function call (Function)
************************************************************************
DEFINE FUNCTION F#TEXT
RETURNS (A20) BY VALUE
DEFINE DATA
PARAMETER
1 #TEXT1 (A5) BY VALUE
1 #TEXT2 (A1) BY VALUE OPTIONAL
LOCAL
1 #FRAME (A3)
END-DEFINE
/*
IF #TEXT2 SPECIFIED
MOVE ALL #TEXT2 TO #FRAME
/*
COMPRESS #FRAME #TEXT1 'world' #FRAME INTO F#TEXT
/*
WRITE F#TEXT
ELSE
COMPRESS #TEXT1 'morning' INTO F#TEXT
/*
END-IF
/*
END-FUNCTION
*
END
According to the function definition, a function call may return a single result field.
This can be a scalar value or an array field, which is processed like a temporary field in
the statement where the function call is embedded. If the result is an array, the function
call must be immediately followed by an array-index-expression
addressing the required occurrences.
For example, to access the first occurrence of the array returned:
#FCT(<#A,#B>)(1)
In order to properly resolve a function call at compile time, the compiler requires the format, length and array structure of the parameters and the function result. The parameters specified in the function call are checked against the corresponding definitions in the function to ensure that they match. If a function is used within a statement instead of an operand, the function result must match the format, length and array structure of the operand.
You have three options to provide this information:
Retrieve the parameter and result specifications implicitly from the cataloged object
(if available) of the called function if no DEFINE PROTOTYPE statement is executed earlier.
This method requires the least amount of programming effort.
Use a DEFINE PROTOTYPE
statement. You have to use a DEFINE PROTOTYPE statement if the cataloged
object of the called function is not available or if the function name is not known at
compile time, that is, instead of a function name the name of an alphanumeric variable
is specified in the function call.
Specify an explicit (IR=) clause in the function call.
The first two methods comprise a full validation of the format, length and array structure of the parameters and the function result.
If neither a DEFINE PROTOTYPE statement nor a cataloged function object
exists, you can use the following clauses in your function call:
The (IR=) clause specifies the function result
format/length/array structure.
This clause determines which format/length/array structure the compiler should
assume for the result field (the intermediate result as used by the statement that
contains the function call). If a prototype definition is available for a function
call, the (IR=) clause overrules the specifications in the prototype.
The (IR=) clause does not enforce any parameter checks.
The (PT=)
clause uses a previously defined prototype with a name other than the function name.
This clause validates the parameters and the function result by using a DEFINE
PROTOTYPE statement with the referenced name.
In the following example, the function #MULT is called, but the
parameter and result specifications from the prototype whose name is
#ADD apply:
#I := #MULT(<(PT=#ADD) 2 , 3>)
The first of the following definitions found is used to check the specified parameters:
the prototype definition referenced in the (PT=) clause;
the prototype definition in the DEFINE
PROTOTYPE statement where the prototype name matches the
function name used in the function call;
the parameter specifications in the cataloged function object which are supplied
with the DEFINE FUNCTION statement.
If none of the above is specified, no parameter validation is performed. This provides you the option to supply any number and layout of parameters in the function call without receiving a syntax error.
The first of the following definitions found is used to check the function result:
the definition provided in the (IR=)
clause;
the RETURNS definition in the prototype referenced in the
(PT=)
clause;
the prototype definition in the DEFINE PROTOTYPE statement where the
prototype name matches the function name used in the function call;
the function result specification in the cataloged function object.
If none of the above is specified, a syntax error occurs.
Program:
** Example 'FUNCBX01': Declare result value and parameters (Program)
************************************************************************
*
DEFINE DATA LOCAL
1 #PROTO-NAME (A20)
1 #PARM1 (I4)
1 #PARM2 (I4)
END-DEFINE
*
DEFINE PROTOTYPE VARIABLE #PROTO-NAME
RETURNS (I4)
DEFINE DATA PARAMETER
1 #P1 (I4) BY VALUE OPTIONAL
1 #P2 (I4) BY VALUE
END-DEFINE
END-PROTOTYPE
*
#PROTO-NAME := 'F#MULTI'
#PARM1 := 3
#PARM2 := 5
*
WRITE #PROTO-NAME(<#PARM1, #PARM2>)
WRITE #PROTO-NAME(<1X ,5>)
*
WRITE F#MULTI(<(PT=#PROTO-NAME) #PARM1,#PARM2>)
*
WRITE F#MULTI(<(IR=N20) #PARM1, #PARM2>)
*
END
Function F#MULTI:
** Example 'FUNCBX02': Declare result value and parameters (Function)
************************************************************************
DEFINE FUNCTION F#MULTI
RETURNS #RESULT (I4) BY VALUE
DEFINE DATA PARAMETER
1 #FACTOR1 (I4) BY VALUE OPTIONAL
1 #FACTOR2 (I4) BY VALUE
END-DEFINE
/*
IF #FACTOR1 SPECIFIED
#RESULT := #FACTOR1 * #FACTOR2
ELSE
#RESULT := #FACTOR2 * 10
END-IF
/*
END-FUNCTION
*
END
All function calls used within a Natural statement are evaluated before the statement execution starts. They are evaluated in the same order in which they appear in the statement. Function result values are stored in temporary fields that are later used as operands for execution of the statement.
Calling a function that has modifiable parameters which are repeatedly used within the same statement can cause different function results as indicated in the following example.
Before the COMPUTE statement is started, variable #I has the
value 1. In a first step, function F#RETURN is executed. This
changes the value of #I to 2 and returns a value of
2 as the function result. After this, the COMPUTE operation
starts and sums up the values of #I (2) and the temporary field
(2) to a value of 4.
** Example 'FUNCCX01': Parameter changed within function (Program)
************************************************************************
DEFINE DATA LOCAL
1 #I (I2) INIT <1>
1 #RESULT (I2)
END-DEFINE
*
COMPUTE #RESULT := #I + F#RETURN(<#I>) /* First evaluate function call,
/* then execute the addition.
*
WRITE '#I :' #I /
'#RESULT:' #RESULT
*
END
** Example 'FUNCCX02': Parameter changed within function (Function)
************************************************************************
DEFINE FUNCTION F#RETURN
RETURNS #RESULT (I2) BY VALUE
DEFINE DATA PARAMETER
1 #PARM1 (I2) BY VALUE RESULT
END-DEFINE
/*
#PARM1 := #PARM1 + 1 /* Increment parameter.
#RESULT := #PARM1 /* Set result value.
/*
END-FUNCTION
*
END
FUNCCX01:
#I : 2 #RESULT: 4
You can also use a function call in place of a Natural statement without embedding the function call in a statement. In this case, the function call need not return a result value; if returned, the result value is discarded.
You can avoid that such a function call is considered to be part of a previous statement
by separating the function call from the previous statement with a semicolon
(;) as shown in the following example.
Program:
** Example 'FUNCDX01': Using a function as a statement (Program)
************************************************************************
DEFINE DATA LOCAL
1 #A (I4) INIT <1>
1 #B (I4) INIT <2>
END-DEFINE
*
*
WRITE 'Write:' #A #B
F#PRINT-ADD(< 2,3 >) /* Function call belongs to operand list
/* immediately preceding it.
*
WRITE // '*************************' //
*
WRITE 'Write:' #A #B; /* Semicolon separates operands and function.
F#PRINT-ADD(< 2,3 >) /* Function call does not belong to the
/* operand list.
*
END
Function:
** Example 'FUNCDX02': Using a function as a statement (Function)
************************************************************************
DEFINE FUNCTION F#PRINT-ADD
RETURNS (I4)
DEFINE DATA PARAMETER
1 #SUMMAND1 (I4) BY VALUE
1 #SUMMAND2 (I4) BY VALUE
END-DEFINE
/*
F#PRINT-ADD := #SUMMAND1 + #SUMMAND2 /* Result of function call.
WRITE 'Function call:' F#PRINT-ADD
/*
END-FUNCTION
*
END
Output of Program FUNCDX01:
Function call: 5 Write: 1 2 5 ************************* Write: 1 2 Function call: 5