OS/2 Procedures Language 2/REXX


Inf-HTML [About][Toc][Index] 0.9b (c) 1995 Peter Childs


Functions


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

                    | +------,-------+ |
                    | v              | |
                    +-++------------++-+
                       +-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  If the routine name exists as a label in the program, the 
           current processing status is saved, so that it will later be 
           possible to return to the point of invocation to resume 
           processing. Control is then passed to the first label in the 
           program that matches the name. As with a routine invoked by the 
           CALL instruction, various other pieces of status information 
           (TRACE and NUMERIC settings and so on) are also saved. See the 
           CALL instruction for details of this. If an internal routine is 
           to be called as a function, you must specify an expression in 
           any RETURN instruction to return from the function.  This is 
           not necessary if the function is called only 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 invokes itself (this is known 
           as 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 later in 
           this section. 
 External  You can write or make use of functions that are external to a 
           program and to the language processor. An external function can 
           be written in any language, including REXX, that supports the 
           system-dependent interfaces used by the language processor to 
           invoke it. Again, when called as a function, it must return 
           data to the caller. 
 
 Notes: 
   1. Calling an external REXX program as a function is similar to calling 
      an internal routine.  The external routine is, however, an implicit 
      PROCEDURE in that all the caller variables are always hidden and the 
      status of internal values (NUMERIC settings and so on) start with 
      their defaults (rather than inheriting those of the caller). 
   2. Other REXX programs can be called as functions. You can use either 
      EXIT or RETURN to leave the invoked REXX program; in either case, 
      you must specify an expression. 
 
 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: 
   1. Functions that have been loaded into the macrospace for pre-order 
      execution 
   2. Functions that are part of a function package. 
   3. REXX functions in the current directory, with the current extension 
   4. REXX functions along environment PATH, with the current extension 
   5. REXX functions in the current directory, with the default extension 
   6. REXX functions along environment PATH, with the default extension 
   7. Functions that have been loaded into the macrospace for post-order 
      execution. 
 
 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  In Example 1, the built-in function BEEP is called as a REXX 
      subroutine. The return value from BEEP is placed in the REXX special 
      variable RESULT. 
   o  Example 2 shows BEEP called as a REXX function. The return value 
      from the function is substituted for the function call. The clause 
      itself is an assignment instruction; the return value from the BEEP 
      function is placed in the variable bc. 
   o  In Example 3, the BEEP function is processed and its return value is 
      substituted in the expression for the function call, just as in 
      Example 2. In this case, however, the clause as a whole evaluates to 
      a single expression; therefore the evaluated expression is passed to 
      the current default environment as a command. 
      Note:    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  The parentheses in a function are always needed, even if no 
      arguments are required. The first parenthesis must follow the name 
      of the function with no space in between. 
   o  The built-in functions work internally with NUMERIC DIGITS 9 and 
      NUMERIC FUZZ 0 and are unaffected by changes to the NUMERIC 
      settings, except where stated. 
   o  You can supply a null string where a string is referenced. 
   o  If an argument specifies a length, it must be a nonnegative whole 
      number. If it specifies a start character or word in a string, it 
      must be a positive whole number, unless otherwise stated. 
   o  Where the last argument is optional, you can always include a comma 
      to indicate that you have omitted it; for example, DATATYPE(1,), 
      like DATATYPE(1), would return NUM. 
   o  If you specify a pad character, it must be exactly one character 
      long. 
   o  If a function has a suboption you can select by specifying the first 
      character of a string, that character can be in uppercase or 
      lowercase letters. 
   o  Conversion between characters and hexadecimal involves the machine 
      representation of character strings, and hence returns appropriately 
      different results for ASCII and EBCDIC machines. 
   o  A number of the functions described in this chapter support the 
      double-byte-character-set (DBCS).  A complete list and description 
      of these functions is given in the OS/2 Procedures Language 2/REXX 
      Reference. 
   

Inf-HTML End Run - Successful