Syntax
You can include function calls to internal and external routines in an expression anywhere that a data term (such as a string) would be valid, using the notation:
──function─name(─┬──────────────────┬─)──── │ ┌──────,───────┐ │ │ │ │ └─┴┬────────────┬┴─┘ └─expression─┘
function-name is a literal string or a single symbol, that is taken to be a constant.
There can be up to a maximum of 20 expressions, separated by commas, between the parentheses. These expressions are called the arguments to the function. Each argument expression may include further function calls.
The ( must be adjacent to the name of the function, with no blank in between, or the construct is not recognized as a function call. (A blank operator is assumed at this point instead.)
The arguments are evaluated in turn from left to right and they are all then passed to the function. This then executes some operation (usually dependent on the argument strings passed, though arguments are not mandatory) and eventually returns a single character string. This string is then included in the original expression as though the entire function reference had been replaced by the name of a variable that contained that data.
For example, the function SUBSTR is built-in to the language processor and could be used as:
N1='abcdefghijk' Z1='Part of N1 is: 'Substr(N1,2,7) /* would set Z1 to 'Part of N1 is: bcdefgh' */
A function call without any arguments must always include the parentheses to be recognized as a function call.
date() /* returns the date in the default format dd mon yyyy */
Calls to Functions and Subroutines
The mechanism for calling functions and subroutines is the same. The only difference is that functions must return data, whereas subroutines need not. The following types of routines can be called as functions:
Internal
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 invokes itself (this is known as recursive invocation). The PROCEDURE instruction ensures that a new variable n is created for each invocation). Built-in
Notes:
Search Order
The search order for functions is the same as in the preceding list. That is, internal labels take first precedence, then built-in functions, and finally external functions.
Internal labels are not used if the function name is given as a string (that is, is specified in quotation marks); in this case the function must be built-in or external. This lets you usurp the name of, for example, a built-in function to extend its capabilities, but still be able to invoke the built-in function when needed.
Example:
/* Modified DATE to return sorted date by default */date: procedure arg in if in='' then in='Sorted' return 'DATE'(in)
Built-in functions have names in uppercase letters. The name in the literal string must be in uppercase for the search to succeed, as in the example. The same is usually true of external functions.
External functions and subroutines have a system-defined search order.
REXX searches for external functions in the following order:
Errors during Execution
If an external or built-in function detects an error of any kind, the language processor is informed, and a syntax error results. Processing of the clause that included the function call is therefore terminated. Similarly, if an external function fails to return data correctly, this is detected by the language processor and reported as an error.
If a syntax error occurs during the processing of an internal function, it can be trapped (using SIGNAL ON SYNTAX) and recovery may then be possible. If the error is not trapped, the program is terminated.
Return Values
A function normally returns a value that is substituted for the function call when the expression is evaluated.
How the value returned by a function (or any REXX routine) is handled depends on whether it is called by a function call or called as a subroutine with the CALL instruction.
A routine called as a subroutine: If the routine returns a value, that value is stored in the special variable named RESULT. Otherwise, the RESULT variable is dropped, and its value is the string "RESULT".
A routine called as a function: If the function returns a value, that value is substituted into the expression at the position where the function was called. Otherwise, REXX stops with an error message.
Examples:
/* Different ways to call a REXX procedure */ call Beep 500, 100 /* Example 1: a subroutine call */ bc = Beep(500, 100) /* Example 2: a function call */ Beep(500, 100) /* Example 3: result passed as */ /* a command */
o
┴╓: Many other languages (such as C) throw away the return value of a function if it is not assigned to a variable. In REXX, however, a value returned as in Example 3 is passed on to the current environment or subcommand handler. If that environment is CMD (the default), then this action will result in the operating system performing a disk search for what seems to be a command.
Built-in Functions
REXX provides a rich set of built-in functions. These include character manipulation, conversion, and information functions.
Here are some general notes on the built-in functions:
o