Just like the SAS DATA step, the SAS IML language supports both functions and subroutines. A function returns a value, so the calling syntax is familiar:
y = func(x1, x2); /* the function returns one value, y */
In this syntax, the input arguments are x1 and x2. The output argument is y.
In contrast, a subroutine either modifies an input argument or returns multiple results in its arguments. A simple example of a subroutine that modifies its input argument is the SORT subroutine. When you execute CALL SORT(x), the input matrix x is sorted. We say that the subroutine overwrites one of its arguments (in this case, the first argument) with the result.
In addition to overwriting one or more arguments, some subroutines support an optional calling syntax: after specifying the required arguments, you can specify optional arguments by using keyword-value pairs. This article explains the keyword-value syntax for specifying optional arguments in SAS IML subroutines.
An example of keyword-value pair syntax for subroutines
Let's look at the SORT subroutine more closely. The full syntax for the subroutine is
CALL SORT(x <, by > <, descend > );
where the second and third arguments are optional. If specified, they indicate columns of the x matrix. The second argument indicates which columns (and which order) to use when sorting. The third argument specifies which columns should be sorted in descending order. So, for example, the documentation for the SORT subroutine contains an example similar to the following:
proc iml; m = { 1 1 0, 2 2 0, 1 2 1, 2 4 1, 1 0 3, 2 0 4}; call sort(m, {1 3}, 3); /* sort by col 1 and 3; descending by col 3 */ print m; |
The call has indeed sorted the matrix by the first column in ascending order and, when there are ties, by the third column in descending order. An issue with this "positional syntax" is that a casual user of the IML language might wonder about the meaning of the second and third arguments. Sure, they could read the documentation, but an alternative is to use keyword-value pairs to specify the optional parameters:
call sort(m) by={1,3} descend=3; /* sort by col 1 and 3; descending by col 3 */ |
This call also sorts the matrix, but the keyword-value pairs make the optional arguments easier to understand. It is clearer that the BY= keyword uses the indices 1 and 3, and that the DESCEND= keyword uses the value 3. A casual user might be able to guess that these values are being used to specify the sorting columns and which columns are sorted in descending order.
How did I know that the keywords are BY and DESCEND? Because the documentation specifies those names in the syntax! In addition, the SAS IML: Language Reference, which includes functions and subroutines in SAS Viya, explicitly states the names of keywords. For example, see the documentation for the QUAD call, which includes sentences such as "You can specify eps by using the EPS keyword."
Optional keywords for user-defined subroutines
Not every SAS IML programmer knows about keyword-value pairs, but even fewer realize that you can use keywords for optional arguments in a user-defined subroutine that you create! Suppose you define the following subroutine, which has three optional parameters:
start FancyPrint(x, colName=, rowName=, labl=parentName("x")); if IsSkipped(colName) then colName = "Col1":compress("Col"+char(ncol(x))); if IsSkipped(rowName) then rowName = "Row1":compress("Row"+char(nrow(x))); print x[c=colName r=rowName label=labl]; finish; |
The optional parameters can be skipped. If you want to specify the third and fourth parameters, you can call the subroutine with a positional syntax as follows:
N = {3 1 4 1 6, 1 4 1 4 2, 2 7 1 8 3}; r = {'pi' 'sqrt(2)' 'e'}; call FancyPrint(N, , r, "Famous Numbers"); |
This positional syntax is fine, but an alternative is to use keyword-value pairs, as follows:
call FancyPrint(N) rowName={'pi' 'sqrt(2)' 'e'} Labl="Famous Numbers"; |
When you use keyword-value pairs, you can specify only the values for some parameters. This is helpful when there are many optional parameters. For example, suppose a subroutine has five optional parameters and you want to specify the fifth. If you use positional syntax, you must type four commas followed by the fifth argument. However, if you use keyword-value pairs, you need to specify only the fifth argument.
Summary
In the SAS IML language, subroutines that have optional arguments often support an alternative syntax. You can use keyword-value pairs to specify optional arguments. This can lead to programs that are more readable, especially when a subroutine has many optional parameters, and you want to override only a few.
Further reading
A section of the SAS IML documentation describes keyword-value pairs. Read the section "Passing Arguments by Using Keyword-Value Pairs" for additional information.
There are some SAS IML functions that have so many optional arguments that the documentation does not show the ordered list of arguments but shows only the keyword-value syntax. Examples include the graphing functions, such as CALL SCATTER.