Modules with Arguments |
Most modules contain one or more arguments, and therefore contain a separate local symbol table. The following statements apply to modules with arguments:
You can specify arguments as variable names, expressions, or literal values.
If you specify several arguments, use commas to separate them.
Arguments are passed by reference, not by value. This means that a module can change the value of an argument. An argument that is modified by a module is called an output argument.
If you have both output arguments and input arguments, the SAS/IML convention is to list the output arguments first.
When a module is run, the input arguments can be a matrix name, expression, or literal. However, you should specify only matrix names for output arguments.
When a module is run, the value for each argument is transferred from the global symbol table to the local symbol table. For example, consider the module Mod2 defined in the following statements:
proc iml; a = 10; b = 20; c = 30; start Mod2(x,y); /* begin module */ p = x+y; x = 100; /* change the value of an argument */ c = 25; finish Mod2; /* end module */ run Mod2(a,b); print a b c;
The first three statements are submitted in the main scope and define the variables a, b, and c. The values of these variables are stored in the global symbol table. The START statement begins the definition of Mod2 and lists two variables (x and y) as arguments. This creates a local symbol table for Mod2. All symbols used inside the module (x, y, p, and c) are in the local symbol table. There is also a correspondence between the arguments in the RUN statement (a and b) and the arguments in the START statement (x and y). Also note that a and b exist only in the global symbol table, whereas x, y, and p exist only in the local symbol table. The symbol c exists in both symbol tables, but the values are completely independent.
When Mod2 is executed with the RUN statement, the local variable x becomes the "owner" of the data in the global matrix a. Similarly, the local variable y becomes the owner of the data in b. Because c is not an argument, there is no correspondence between the value of c in the global table and the value of c in the local table. When the module finishes execution, the variables a and b at main scope regain ownership of the data in x and y, respectively. The local symbol table that contains x and y is deleted. If the data were modified within the module, the values of a and b reflect the change, as shown in Figure 6.4.
a | b | c |
---|---|---|
100 | 20 | 30 |
Notice that after the module is executed, the following are true:
a is changed to 100 since the corresponding argument, x, was changed to 100 inside the module.
b is still 20.
c is still 30. Inside the module, the local symbol c was set to 25, but there is no correspondence between the global symbol c and the local symbol c.
Also note that, inside the module, the symbols a and b do not exist. Outside the module, the symbols p, x, and y do not exist.
Functions are special modules that return a single value. To write a function module, include a RETURN statement that specifies the value to return. The RETURN statement is necessary for a module to be a function. You can use a function module in an assignment statement, as you would a built-in function.
The symbol-table logic described in the preceding section also applies to function modules. In the following function module, the value of c in the local symbol table is assigned to the symbol z at main scope:
proc iml; a = 10; b = 20; c = 30; start Mod3(x,y); c = 2#x + y; return (c); /* return function value */ finish Mod3; z = Mod3(a,b); /* call function */ print a b c z;
a | b | c | z |
---|---|---|---|
10 | 20 | 30 | 40 |
Notice the following about this example:
a is still 10 and b is still 20.
c is still 30. The symbol c in the global table has no connection with the symbol c in the local table.
z assigned the value 40, which is the value returned by the module.
Again notice that, inside the module, the symbols a, b, and z do not exist. Outside the module, the symbols x and y do not exist.
In the next example, you define your own function module, Add, which adds its two arguments:
proc iml; start Add(x,y); sum = x+y; return(sum); finish; a = {9 2, 5 7}; b = {1 6, 8 10}; c = Add(a,b); print c;
c | |
---|---|
10 | 8 |
13 | 17 |
Function modules can also be called as arguments to other modules or to built-in functions. For example, in the following statements, the Add module is called twice, and the results from those calls are used as arguments to call the Add module a third time:
d = Add(Add({1 2},{3 4}), Add({5 6}, {7 8})); print d;
d | |
---|---|
16 | 20 |
Functions are resolved in the following order:
SAS/IML built-in functions
user-defined function modules
SAS DATA step functions
Because of this order of resolution, it is an error to try to define a function module that has the same name as a SAS/IML built-in function.
For modules with arguments, the variables used inside the module are local and have no connection with any variables that exist outside the module in the global table. However, it is possible to specify that certain variables not be placed in the local symbol table but rather be accessed from the global table. The GLOBAL clause specifies variables that you want to share between local and global symbol tables. The following is an example of a module that uses a GLOBAL clause to define the symbol c as global. This defines a one-to-one correspondence between the value of c in the global symbol table and the value of c in the local symbol table.
proc iml; a = 10; b = 20; c = 30; start Mod4(x,y) global (c); x = 100; c = 40; b = 500; finish Mod4; run Mod4(a,b); print a b c;
The output is shown in Figure 6.8.
a | b | c |
---|---|---|
100 | 20 | 40 |
After the module is called, the following facts are true:
a is changed to 100.
b is still 20 and not 500, since b exists independently in the global and local symbol tables.
c is changed to 40 because it was declared to be a global variable. The matrix c inside the module is the same matrix as the one outside the module.
Because every module with arguments has its own local table, it is possible to have many local tables. You can use the GLOBAL clause with many (or all) modules to share a single global variable among many local symbol tables.