The SAS IML Language has a quirk with regards to functions that take no arguments. As discussed in the documentation, "modules with arguments are given a local symbol table." This is the usual behavior that programmers expect. However, the documentation goes on to state that "a module that has no arguments shares the global symbol table. All variables in such a module are global."
I think this behavior is a throwback to early days in which modules were subroutines (not functions) within the main program that encapsulated certain computations. You could call the subroutine and return from it, but the variables were all defined at the main scope and used the global symbol table. A subroutine does not return a value. Instead, it updates one or more existing variables that are global in scope.
Let's look at an example for which it is useful to define a function that has not arguments. Suppose you want to create a helper function in SAS IML that returns the "lemniscate constant", which is the value \( \omega = \Gamma(1/4)^2 / (2 \sqrt{2 \pi}) \). The approximate value of the constant is 2.6220575542921198. (Interesting fact: the lemniscate constant is related to the arithmetic-geometric mean between 1 and sqrt(2).)
You might attempt to write the following function, which demonstrates two errors:
proc iml; /* WRONG WAY to define a function that takes no arguments! */ start Lemniscate(); gamma = Gamma(1/4); pi = constant("pi"); sqrt2pi = sqrt(2*pi); return( gamma**2 / (2*sqrt2pi) ); finish; |
If you submit these statements, SAS will report two problems:
- ERROR: Expecting a name. This error occurs on the START statement. It tells you that empty argument lists are invalid for functions.
- WARNING: RETURN statement with argument only allowed in modules with arguments. This error occurs on the RETURN statement. You can return a value only from a properly defined function.
I'm not going to try to justify this behavior, but here's how to work around it. First, create a dummy argument. Then make the argument optional by assigning it a default value. Since the argument is optional, you do not need to specify it when you call the function! Thus, the following statements define a function that has no required arguments:
proc iml; /* define a module that has no required arguments */ start Lemniscate(dummy=0); /* the argument is ignored */ gamma = Gamma(1/4); pi = constant("pi"); sqrt2pi = sqrt(2*pi); return( gamma**2 / (2*sqrt2pi) ); finish; w = Lemniscate(); /* call the function without specifying an argument */ print w[F=16.14]; |
![](https://blogs.sas.com/content/iml/files/2024/08/funcnoargs2.png)
As shown in the program, you can call the function by using an empty argument list. In fact, you could also call it with an argument, but that would be confusing because the argument is ignored by the computations inside the function. In either case, the function returns a result that does not depend on the input argument. This logic is summarized in the following flowchart:
![](https://blogs.sas.com/content/iml/files/2024/08/funcnoargs1.png)
Summary
For historical reasons, you can't define a SAS IML function that has an empty argument list. A workaround is to define the function with one optional argument. You can then call the function as expected. The variables inside the function will be local in scope.