PROCEDURE

>>-PROCEDURE--+------------------------+--;--------------------><
              |         +------------+ |
              |         V            | |
              +-EXPOSE----+-name---+-+-+
                          +-(name)-+

PROCEDURE, within an internal routine (subroutine or function), protects the caller's variables by making them unknown to the instructions that follow it. After a RETURN instruction is processed, the original variables environment is restored and any variables used in the routine (that were not exposed) are dropped. (An exposed variable is one belonging the caller of a routine that the PROCEDURE instruction has exposed. When the routine refers to, or alters, the variable, the original (caller's) copy of the variable is used.) An internal routine need not include a PROCEDURE instruction. In this case the variables it is manipulating are those the caller owns. If the PROCEDURE instruction is used, it must be the first instruction processed after the CALL or function invocation; that is, it must be the first instruction following the label.

If you use the EXPOSE option, any variable specified by the name is exposed. Any reference to it (including setting and dropping) is made to the variables environment the caller owns. Hence, the values of existing variables are accessible, and any changes are persistent even on RETURN from the routine. If the name is not enclosed in parentheses, it identifies a variable you want to expose and must be a symbol that is a valid variable name, separated from any other name with one or more blanks.

If parentheses enclose a single name, then, after the variable name is exposed, the character string value of name is immediately used as a subsidiary list of variables. Blanks are not necessary inside or outside the parentheses, but you can add them if desired. This subsidiary list must follow the same rules as the original list, that is, valid variable names separated by blanks, except that no parentheses are allowed.

Variables are exposed from left to right. It is not an error to specify a name more than once, or to specify a name that the caller has not used as a variable.

Any variables in the main program that are not exposed are still protected. Therefore, some of the caller's variables can be made accessible and can be changed, or new variables can be created. All these changes are visible to the caller upon RETURN from the routine.

Example:

/* This is the main Rexx program */
j=1; z.1="a"
call toft
say j k m       /* Displays "1 7 M"          */
exit

/* This is a subroutine     */
toft: procedure expose j k z.j
  say j k z.j   /* Displays "1 K a"          */
  k=7; m=3      /* Note: M is not exposed    */
  return

Note that if Z.J in the EXPOSE list is placed before J, the caller's value of J is not visible, so Z.1 is not exposed.

The variables in a subsidiary list are also exposed from left to right.

Example:

/* This is the main Rexx program */
j=1;k=6;m=9
a ="j k m"
call test
exit

/* This is a subroutine     */
test: procedure expose (a)   /* Exposes A, J, K, and M     */
  say a j k m                /* Displays "j k m 1 6 9"     */
  return

You can use subsidiary lists to more easily expose a number of variables at a time or, with the VALUE built-in function, to manipulate dynamically named variables.

Example:

/* This is the main Rexx program */
c=11; d=12; e=13
Showlist="c d"     /* but not E              */
call Playvars
say c d e f        /* Displays "11 New 13 9" */
exit

/* This is a subroutine     */
Playvars: procedure expose (showlist) f
  say word(showlist,2)              /* Displays "d"                     */
  say value(word(showlist,2),"New") /* Displays "12" and sets new value */
  say value(word(showlist,2))       /* Displays "New"                   */
  e=8                               /* E is not exposed                 */
  f=9                               /* F was explicitly exposed         */
  return

Specifying a stem as name exposes this stem and all possible compound variables whose names begin with that stem. (See .)

Example:

/* This is the main Rexx program */
a.=11; i=13; j=15
i = i + 1
C.5 = "FRED"
call lucky7
say a. a.1 i j c. c.5
say "You should see 11 7 14 15 C. FRED"
exit

lucky7:Procedure Expose i j a. c.
  /* This exposes I, J, and all variables whose     */
  /* names start with A. or C.                      */
  A.1="7"  /* This sets A.1 in the caller-'s         */
           /* environment, even if it did not       */
           /* previously exist.                     */
  return

Note: Variables can be exposed through several generations of routines if they are included in all intermediate PROCEDURE instructions.

See the CALL instruction and function descriptions in CALL and Functions for details and examples of how routines are called.