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 variable 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
whitespace characters.
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. Whitespace characters 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 whitespace
characters, 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 2.25. Instructions — PROCEDURE
/* 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 2.26. Instructions — PROCEDURE
/* 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 2.27. Instructions — PROCEDURE
/* 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.
Example 2.28. Instructions — PROCEDURE
/* 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
Variables can be exposed through several generations
of routines if they are included in all intermediate PROCEDURE instructions.