Functions and Subroutines

Functions and subroutines are called in the same way. The only difference between functions and subroutines is that functions must return data, whereas subroutines need not.

The following types of routines can be called as functions:

Internal

If the routine name exists as a label in the program, the current processing status is saved for a later return to the point of invocation to resume execution. Control is then passed to the first label in the program that matches the name. As with a routine called by the CALL instruction, status information, such as TRACE and NUMERIC settings, is saved too. See the CALL instruction (CALL) for details.

If you call an internal routine as a function, you must specify an expression in any RETURN instruction so that the routine can return. This is not necessary if it is called as a subroutine.

Example:

/* Recursive internal function execution... */
arg x
say x"! =" factorial(x)
exit
factorial: procedure   /* Calculate factorial by    */
  arg n                /*   recursive invocation.   */
  if n=0 then return 1
  return  factorial(n-1) * n
  

FACTORIAL is unusual in that it calls itself (this is recursive invocation). The PROCEDURE instruction ensures that a new variable n is created for each invocation.

Built-in

These functions are always available and are defined in Built-in Functions.

External

You can write or use functions that are external to your program and to the language processor. An external routine can be written in any language, including Rexx, that supports the system-dependent interfaces the language processor uses to call it. You can call a Rexx program as a function and, in this case, pass more than one argument string. The ARG, PARSE ARG, or USE ARG instruction or the ARG built-in function can retrieve these argument strings. When called as a function, a program must return data to the caller.

Notes:

  1. Calling an external Rexx program as a function is similar to calling an internal routine. For an external routine, however, the caller's variables are hidden. To leave the called Rexx program, you can use either EXIT or RETURN. In either case, you must specify an expression.

  2. You can use the INTERPRET instruction to process a function with a variable function name. However, avoid this if possible because it reduces the clarity of the program.

Search Order

Functions are searched in the following sequence: internal routines, built-in functions, external functions.

The name of internal routines must not be specified as a literal string, that is, in quotation marks, whereas the name of built-in functions or external routines must be specified in quotation marks. Be aware of this when you want to extend the capabilities of an existing internal function, for example, and call it as a built-in function or external routine under the same name as the existing internal function. In this case, you must specify the name in quotation marks.

Example:

/* This internal DATE function modifies the          */
/* default for the DATE function to standard date.   */
date: procedure
  arg in
  if in="" then in="Standard"
  return "DATE"(in)
  

Built-in functions have uppercase names, and so the name in the literal string must be in uppercase for the search to succeed. File names can be in uppercase, lowercase, or mixed case. The operating system uses a case-insensitive search for files. When calling a Rexx subroutine, the case of the name does not matter.

External functions and subroutines have a system-defined search order.

The search order for external functions is as follows:

  1. Functions defined on ::ROUTINE directives within the program.

  2. Public functions defined on ::ROUTINE directives of programs referenced with ::REQUIRES.

  3. Functions that have been loaded into the macrospace for preorder execution. (See the Open Object Rexx: Programming Guide for details.)

  4. Functions that are part of a function package. (See the Open Object Rexx: Programming Guide for details.)

  5. Rexx functions in the current directory, with the current extension.

  6. Rexx functions along environment PATH, with the current extension.

  7. Rexx functions in the current directory, with the default extension (.REX or .CMD).

  8. Rexx functions along environment PATH, with the default extension (.REX or .CMD).

  9. Functions that have been loaded into the macrospace for postorder execution.

The full search pattern for functions and routines is shown in Function and Routine Resolution and Execution.

Errors during Execution

If an external or built-in function detects an error, the language processor is informed, and a syntax error results. Execution of the clause that included the function call is, therefore, ended. Similarly, if an external function fails to return data correctly, the language processor detects this and reports it as an error.

If a syntax error occurs during the execution of an internal function, it can be trapped (using SIGNAL ON SYNTAX) and recovery might then be possible. If the error is not trapped, the program is ended.

Figure 7-1. Function and Routine Resolution and Execution