Function Call

#### Search Results

Search

# 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

- Restrictions

- Syntax Description

- Example

- Function Result

- Parameter and Result Specifications

- Evaluation Sequence of Functions in Statements

- Using a Function as a Statement

## 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=` |  | format-length [/array-definition] |
[(array-definition)] `HANDLE OF OBJECT`
( |  | A U B |  | [/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

| n `X` |
|  |  |  | `M` `O` `A` |  |  |
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:

- Called Function F#ADDITION

- Called Function F#CHAR

- Called Function F#EVEN

- Called Function F#TEXT

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

- Validation of Parameters and Function Result

- Example with Multiple Definitions in a Function Call

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

### On this page

- Function
- Restrictions
- Syntax Description
- Example
- Function Result
- Parameter and Result Specifications
- Evaluation Sequence of Functions in Statements
- Using a Function as a Statement