If a REXX function does not need to use the variables which the rest of the script creates, or if the function uses variables which the rest of the script does not need to access, then you can start the function with the PROCEDURE instruction. This clears all the existing variables away out of sight, and prepares for a new set of variables. This new set will be destroyed when the function returns. The advantage to this is that it ensures that the function won't ever alter the value of any variable used by the rest of your script, even if the function creates a variable with the same name as one used elsewhere in your script. (ie, The variable in the function belongs to an entirely different set of variables than the one with the same name elsewhere). Likewise, if a function calls another function which contains the PROCEDURE instruction, that second function won't alter the values of any variables used by the first function. So, PROCEDURE is a way to protect variables from being inadvertently altered by calls to functions.

The following script calculates the factorial of a number recursively. PROCEDURE makes recursion possible and easy.

/* Calculate factorial x, that is, 1*2*3* ... *x  */
SAY "Enter a number"
PARSE PULL num .
SAY num "!=" factorial(num)
EXIT

factorial: /* calculate the factorial of the argument */
   PROCEDURE
   num = ARG(1)
   IF num < 3 THEN RETURN num
   ELSE RETURN factorial(num-1) * p
First of all, the num variable initially passed to factorial is not the same num variable used within factorial due to the PROCEDURE instruction. So, that ARG() assignment isn't altering the original num variable, but rather, creating a new variable named num. Furthermore, that second num variable is then passed to factorial again. (ie, factorial calls itself when it goes to return a value). When factorial is called again, it creates yet another num variable to be used up until that nested call returns.


Exposing variables

If your function needs access to just a few variables used elsewhere in the script, but wants to protect all other variables, then put the EXPOSE keyword after PROCEDURE, followed by any variable names that you don't want hidden away. In this way, your function can alter the values of particular variables used elsewhere in the script, while also protecting other variables. Consider the following:

/* Assign values to variables First and Second */
First = 0
Second = 0
/* Call subroutine alter */
CALL alter
SAY "First =" First", Second =" Second
EXIT

alter:
   PROCEDURE EXPOSE First /* don't protect the variable First */
   First = 1
   Second = 1
   RETURN
The above prints out "First = 1, Second = 0". Note that the alter function was able to change the value of First used in the SAY command, but not the value of Second. That's because the Second variable that alter changes is an entirely different variable than the Second variable used elsewhere in the script. On the other hand, the First variable used within alter is the very same one used elsewhere.

You can also specify the name of some variable whose value contains the names of which variables you want EXPOSE'ed. You put that variable's name in parentheses after the EXPOSE keyword.

/* Set the variable MyVar to the names of what other
 * variables we want exposed.
 */
MyVar = 'SomeVar MyArray. SomeCompound.1'

/* Now call alter(). */
CALL alter
EXIT

alter:
   PROCEDURE EXPOSE (MyVar) /* Same as PROCEDURE EXPOSE MyVar SomeVar MyArray. SomeCompound.1 */
   RETURN
Note: The variable whose name is in parentheses is also exposed.