Function Call

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:


Function

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.

Restrictions

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;

  • in an AT BREAK or IF BREAK statement;

  • 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).

Syntax Description

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:

function-name is either of the following:

  • the name of the function to be called as referenced in the DEFINE FUNCTION statement, or

  • the name of an alphanumeric variable which contains the name of the called function at execution time. This variable has to be referenced in a prototype definition with the VARIABLE keyword of the DEFINE PROTOTYPE statement. If this prototype does not contain the correct parameter and result field definitions, another prototype can be assigned with the prototype-clause.

prototype-clause
Prototype Clause:

See prototype-clause (PT=).

intermediate-result-clause
Intermediate Result Clause:

See intermediate-result-clause (IR=).

parameter
Parameter Specification:

See parameter.

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.

prototype-clause (PT=)

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:

prototype-name is either of the following:

  • the name of the prototype whose result and parameters layouts are to be used, or

  • the name of an alphanumeric field specified as function-name in a function call. This field must contain the name of the function to be called at execution time.

    An array index expression must not be specified with the field name.

intermediate-result-clause (IR=)

  IR=

Curly Bracket Opened

format-length [/array-definition]

Curly Bracket Opened

[(array-definition)] HANDLE OF OBJECT
(

Curly Bracket Closed

A
U
B

Curly Bracket Closed

[/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 DYNAMIC.

For further information on processing dynamic variables, see Introduction to Dynamic Variables and Fields.

parameter

Curly Bracket Opened

nX      

Curly Bracket Closed

 

Bracket Opened

 

Curly Bracket Opened

M
O
A

Curly Bracket Closed

 

Bracket Closed

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 nX you can specify that the next n parameters are to be skipped (for example, 1X to skip the next parameter, or 3X to skip the next three parameters); this means that for the next n parameters no values are passed to the function.

A parameter that is to be skipped must be defined with the keyword OPTIONAL in the function's DEFINE DATA PARAMETER statement. OPTIONAL means that a value can - but need not - be passed from the invoking object to such a parameter.

AD=
Attribute Definition:

If operand is a variable, you can mark it in one of the following ways:

AD=O
Non-modifiable:

See session parameter AD=O.

Note:
Internally, AD=O is processed in the same way as BY VALUE (see the section parameter-data-definition in the description of the DEFINE DATA statement).

AD=M
Modifiable:

See session parameter AD=M.

This is the default setting.

AD=A
Input only:

See session parameter AD=A.

Note:
If operand is a constant, the attribute definition AD cannot be explicitly specified. For constants, AD=O always applies.

Example

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.

Invoking Program FUNCEX01:

** 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   

Output of Program FUNCEX01

Sum of #B,#C      5        
Character A found                             
     2 is an even number            
*** Hello world ***                 
Good morning 

Called Function F#ADDITION

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 

Called Function F#CHAR

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  

Called Function F#EVEN

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 

Called Function F#TEXT

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 

Function Result

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)

Parameter and Result Specifications

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:

  1. 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.

  2. 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.

  3. 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.

Additional Clauses for the Function Call

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>)

Validation of Parameters and Function Result

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.

Example with Multiple Definitions in a Function Call

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 

Evaluation Sequence of Functions in Statements

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.

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.

Program:

** 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

Function:

** 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

Output of Program FUNCCX01:

#I     :      2    
#RESULT:      4

Using a Function as a Statement

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.

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