FUNCTION statement
Defines or declares a prototype for a user-defined function, or declares a Web service operation. The following syntax boxes describe the syntax for each use of the statement, beginning with a user-defined function definition.
Syntax
Use the following syntax to declare a user-defined function prototype that is defined later in the same procedure or that is defined in another external procedure:
Use the following syntax to declare a Web service operation. For more information on declaring Web service operations, see OpenEdge Development: Web Services.
function-name
The name of the function. You must avoid ABL reserved keywords. For a list of ABL keywords, see the Keyword Index in this manual.[ RETURNS ]return-type
Indicates the data type of the function return value. You can specifyreturn-type
as one of the following data types. For more information on each data type, see the Data types reference entry:
object-type-name
Specifies the type name of an ABL or .NET class or interface. Specify an object type name using the syntax described in the Type-name syntax reference entry. With an appropriate USING statement, you can also specify a class or interface name alone, without the qualifying package or namespace.CLASS
If the specified class or interface type name conflicts with an abbreviation of a built-in primitive type name, such as INT for INTEGER, you must specify the CLASS keyword.For a class or interface return value, ABL returns an object reference associated with the class or interface, not a class instance itself. For more information on object references, see the Class-based object reference reference entry.EXTENT [constant
]
Defines the return value as an array of data elements with the specified primitive or object type. This option can specify an array return value as either determinate (has a defined number of elements) or indeterminate (has an undefined number of elements). To define a determinate array return value, specify the EXTENT option with theconstant
argument. This optional argument is an integer value that represents the number of elements in the array. To define an indeterminate array return value, specify the EXTENT option without theconstant
argument.An indeterminate array return value can be in one of two states: fixed or unfixed, meaning it either has a fixed dimension or it does not. An indeterminate array return value has an unfixed dimension when first defined. You can fix the dimension of an indeterminate array return value by:
- Setting the number of elements in the array return value using the EXTENT statement
- Assigning a determinate array to the indeterminate array value, fixing it to the dimension of the determinate array
- Passing array parameters to a procedure, user-defined function, or class-based method, so that the indeterminate array value is the target for the passing of a determinate array, fixing the indeterminate array to the dimension of the determinate array
Once fixed, ABL treats a fixed indeterminate array as a determinate array.If you do not use the EXTENT option (or you specifyconstant
as 0), the return value is not an array return value.Note: If you invoke a function on an AppServer, the function cannot return a value as a LONGCHAR, MEMPTR, or CLASS.PRIVATE
Indicates the following about the user-defined function:
- That it cannot be invoked from an external procedure—that is, from a procedure file external to the current procedure file.
- That the INTERNAL-ENTRIES attribute on the procedure that defines it does not provide its name (unless the procedure that defines it is the current procedure file).
- That the GET-SIGNATURE( ) method on the procedure that defines it does not provide its signature (unless the procedure that defines it is the current procedure file).
(parameter
[ ,parameter
] ... )
Defines one or more parameters of the function.For information on the parameter definition syntax, see the Parameter definition syntax reference entry.function-body
function-logic
The logic of the function. This logic can contain the ABL statements allowed within a procedure block, with the following differences:
- The RETURN ERROR statement returns the Unknown value (
?
) for the function, regardless of its return type, but does not raise ERROR in the caller.- You cannot make direct or indirect reference to statements that block for input (namely, the CHOOSE, INSERT, PROMPT-FOR, READKEY, SET, UPDATE, and WAIT-FOR statements).
To return a function value of the data type specified byreturn-type
, you can execute the RETURN statement to set a value of that data type to return at run time. If you omit the RETURN statement, the function returns the Unknown value (?
), regardless of the data type specified byreturn-type
.Ifreturn-type
is defined as a .NET array of mapped types (for example, "System.Byte[]"), you must return an object reference of the specified .NET array of mapped types in the RETURN statement. You cannot return an ABL array of a type that maps to the .NET array type (for example, INTEGER EXTENT) or the AVM raises a run-time error. If you do not execute any RETURN statement forreturn-type
in thefunction-logic
, the user-defined function returns the Unknown value (?
) as its return value.Each logic statement must end with a period.catch-block
Specifies a CATCH statement that defines error handling code for one or more error types. A DO block does not have any default error handling. Therefore, a DO block must have error handling options specified such that it becomes an undoable block. Otherwise, ABL generates a compiler warning. For more information oncatch-block
, see the CATCH statement reference entry.
finally-block
Specifies a FINALLY statement that defines the processing that must occur after all other processing in the block occurs. For more information onfinally-block
, see the FINALLY statement reference entry.END [ FUNCTION ]FORWARD
Declares a prototype for a function in a procedure whose definition appears later in the same procedure. You must declare a user-defined function prototype when the function definition appears within the same procedure following the first use of the function. This prototype must appear in the procedure before the first use of the function.The FUNCTION statement with the FORWARD option must include the following information on the function: the data type it returns, and the data type and mode (INPUT, OUTPUT, or INPUT-OUTPUT) of each parameter.If you declare a function prototype, reference it, and do not define it before the end of the procedure, the compiler returns an error.[ MAP [ TO ]actual-name
] INproc-handle
Declares prototype for a function that resides in a procedure external to the declaring procedure, with the following information:
- Optionally, that
function-name
(the second element in the FUNCTION statement) is an alias (alternative name) for the function and thatactual-name
is the name that appears in the function definition.- The definition of the function resides in another external procedure specified by
proc-handle
, which represents an expression that evaluates to a handle to the procedure that defines the function. This procedure can be an active procedure in the local context or a remote persistent procedure. For more information on remote user-defined functions, see OpenEdge Application Server: Developing AppServer Applications.Note: The MAP option might simplify your code if it references two different user-defined functions that have the same name but that reside in different procedures.A FUNCTION statement with the INproc-handle
option must include the following information on the function: the data type it returns, and the data type and mode (INPUT, OUTPUT, or INPUT-OUTPUT) of each parameter.IN SUPERoperationName
hPortType
ExamplesThe first example,
r-udf1.p
, defines and references the user-defined function doubler(), which accepts an integer and returns the integer multiplied by two:
The second example,
r-udf2.p
, declares a prototype for, references, and defines doubler( ):
The third example consists of two procedures,
r-udf3.p
andr-udfdef.p
. The example illustrates defining a prototype for user-defined function that is defined in an external procedure.The procedure,
r-udf3.p
, declares the prototype for doubler(), runsr-udfdef.p
persistently, invokes doubler(), and deletes the persistent procedure:
The second procedure,
r-udfdef.p
, defines doubler():
To start the third example, run
r-udf3.p
in the Procedure Editor.In the fourth example,
r-fctrl2.p
, the user-defined functionfact()
implements the factorial function, common in probability and statistics, and commonly notated “!
”(6! = 6 x 5 x 4 x 3 x 2 x 1; 100! = 100 x 99 x 98 x ... x 3 x 2 x 1)
:
Notes
- You can terminate a FUNCTION statement with either a period (.) or a colon (:), but typically use a colon (:) for a function definition and a period (.) for a function prototype or to declare a Web service operation.
- Before you reference a user-defined function within a procedure, you must define it, declare its prototype, declare it as external (by using FUNCTION statement’s IN option), or define it.
- You cannot define shared objects, work tables, temp-tables, or ProDataSet objects within a user-defined function.
- ABL implements scalar and array parameters of user-defined functions as NO-UNDO variables.
- A reference to a user-defined function must match the declared prototype or definition with respect to the return type, and with respect to the number, type, and mode of the parameters.
- When an ABL predicate (such as a WHERE clause) contains a user-defined function, the AVM evaluates the function once—when it opens the query or enters the FOR EACH block.
- When the AVM encounters a user-defined function declared externally that references a user-defined function declared externally that references a user-defined function declared externally, etc., the AVM tolerates up to 64 levels of indirection. At the 65th level, the AVM raises an error and returns the Unknown value (
?
).- If a user-defined function has one or more buffer parameters and its definition resides in another procedure, the referencing procedure and the defining procedure must reside on the same machine. If a user-defined function does not have buffer parameters, the invoking procedure and the defining procedure can reside on different machines.
- When you invoke a user-defined function (or a built-in function), you do not need to assign the function’s return value to a variable. That is, you can invoke a user-defined function as a statement, ignoring the return value. You might use this technique with a function that performs some action on a persistent object, such as a shared variable, when you want the action to occur and do not need to check the return value. For example:
- When you invoke a user-defined function, you may pass a TABLE, TABLE-HANDLE, DATASET, or DATASET-HANDLE parameter by value, by reference, or by binding using the BY-VALUE, BY-REFERENCE, or BIND keyword, respectively. For example:
For more information about passing these parameters by value, by reference, or by binding, see the Parameter passing syntax reference entry.- To return an error to the caller from a user-defined function, you can:
- Migrate from using a user-defined function defined within a procedure to using a method defined within a class.
- Use the ROUTINE-LEVEL ON ERROR UNDO, THROW statement in conjunction with the THROW option of the UNDO statement or the ON ERROR phrase in the user-defined function block.
- Use the THROW option of the UNDO statement or the ON ERROR phrase from a CATCH block (CATCH statement) within the user-defined function block.
- Invoke the STOP statement to raise the STOP condition in the caller.
See alsoDYNAMIC-FUNCTION function, METHOD statement, Parameter definition syntax, PROCEDURE statement, RETURN statement
OpenEdge Release 10.2B
|