A second important aspect of the REXX data model involves the scope of variable names. To begin with, each separate REXX program maintains its variables independently of every other REXX program. In other words, REXX variables named in one program file are completely unrelated to those named in another file. In fact, one REXX program's variables are completely inaccessible from any other REXX program's variables. This is usually an advantage in working with a system of multiple REXX programs, since naming conflicts cannot occur. On the other hand, it can also be an inconvenience when sharing data is necessary.

Within a single REXX program, the scoping rules have to do with exactly when the same variable name refers to the same data. The only time the scope of a name is an issue is when internal procedures are invoked. In the examples of procedures already given, there has been just a single scope for all names. That is, names used in one procedure will refer to the same data when used in other procedures that the first procedure either calls or is called from. Such names are "global," and this is the default in REXX.

It is often convenient, however, to use the same name for different data in different procedures. For instance, it is common to use variables like I and J as loop control variables. In fact, it is both a nuisance and a frequent source of errors to have to provide unique names for loop variables in all procedures. Further, to avoid unintended side effects, it is usually good practice to isolate separate procedures from each other by giving each' a unique "name space" and eliminating the possibility of variable naming conflicts. Therefore, REXX provides a way for any procedure to hide its own variables from any procedure, which invokes it. This is done with the PROCEDURE statement. If used, it must immediately follow the label which names the procedure:


In this example, there is one new instruction, ARG, whose purpose is to assign the procedure's argument to the variable RADIUS. Because of the PROCEDURE instruction, all variables in this procedure (RADIUS and PI) are local to the procedure and distinct from any variables with the same name in the calling procedure. In particular, they are undefined until they receive a value from an assignment or an instruction like ARG. The variables used in the calling procedure are hidden from the called procedure and from any procedure which the called procedure might call in turn. Likewise, the variables of the called procedure are hidden from the caller. However, the variables of the called procedure are not necessarily hidden from any procedure it calls, unless the latter also begins with a PROCEDURE statement.

Although purely local variables are probably preferable as the rule, global variables are often very useful as an exception. It is possible to use an option on the PROCEDURE statement to explicitly name variables that are to be shared. For instance, it's inconvenient and inefficient to assign a value to PI in every procedure that uses it, since PI is really a constant. Therefore, one would normally assign its value just once in the main procedure and use the EXPOSE option to make it available in procedures that need it with the instruction


If there is a chain of several calling procedures, each must EXPOSE any variables that are to be shared. REXX scoping rules are dynamic in nature, rather than static. This means that it is not possible to determine by a syntactic analysis of the program when a given name actually refers to the same data. Instead, this always depends on the exact sequence of procedures, which are called. In this case, assuming PI is first assigned in the main procedures, the same data will be available to the AREA procedure only if all other procedures in the calling hierarchy either do not use a PROCEDURE instruction or else explicitly expose PI.

A related issue is the way in which arguments are passed to procedures. Every procedure (or function) call may supply zero or more arguments. For a function call, the arguments are in the form of a list of values, separated by commas, and all enclosed in parentheses. For instance, to use the area function defined above, one might have:



In REXX, arguments are always passed by value. This means that arguments are evaluated when the procedure is called and only the resulting value is available to the procedure. The procedure can change the value of a variable, which happens to be used as an argument only if no PROCEDURE statement occurs in the procedure or if the variable is explicitly exposed. Even if the value of a variable is changed in this way, the value passed as an argument is not changed, since it was computed when the procedure was called. Notice that in the current example, the symbol radius refers to different variables in the called and calling procedures because of the PROCEDURE statement, and the fact that the same symbol is used is merely a (possibly confusing) coincidence.

REXX procedures, which are not functions, i.e., do no return values, are invoked with the CALL instruction, and their arguments are also specified as a list of values, but the list is not enclosed in parentheses. (This is a source of frequent confusion in REXX.) If we changed the area example slightly so that it was simply a procedure invoked only for its side effect, it might look like this:


There are several ways of accessing the arguments passed to a procedure. So far, we have illustrated only the ARG instruction. Although it has the appearance of a declaration, it is not. Instead, ARG is an executable instruction which causes the assignment of the first argument to the named variable, just as if an "=" assignment operator were used. If the variable in question happened to be exposed, its value would be changed even in the calling procedure.

If the procedure has more than one argument, then more than one variable name can be used in the ARG instruction, each name separated from the others by commas. For instance, we might modify our example to display the area of a rectangle instead of a circle:


ARG assigns arguments to variables in the same order as they occur in the argument list. ARG, like PULL, is a special case of the general REXX PARSE instruction, because it is just shorthand for PARSE UPPER ARG. Hence, it can do interesting character string parsing as well. But in the most common case, as illustrated here, there is a one-to-one correspondence between arguments passed and variables. In this case, you might just remember that there should be as many commas in the list following ARG as there are in the argument list that is passed.

The other main way of accessing arguments is with the ARG( ) built-in function. The argument passed to A RG () is the number of the argument passed to the current procedure, and its value is the value of that argument. Here is a completely equivalent form of the last example:

All rights reserved © 2020 Wisdom IT Services India Pvt. Ltd Protection Status

IBM Mainframe Topics