I received the following email from a SAS/IML programmer:
I am getting an error in a PROC IML module that I wrote. The SAS Log says
NOTE: Paused in module NAME
When I submit other commands, PROC IML doesn't seem to understand them. How can I continue the program? The only thing that works is to QUIT and resubmit the entire PROC IML program.
I'm glad you asked this question. Handling run-time errors that occur in user-defined modules can be frustrating unless you understand what the "Paused in module" message means. If you haven't already read my article on scope, local, and global variables in SAS/IML, you might want to read it now. It explains about local scope (inside a module) versus main scope (outside of any module). Also, familiarize yourself with the difference between a syntax error and a run-time error.
A run-time error in a module causes PROC IML to pause
Remember that the "I" in "IML" stands for interactive. When there is a run-time error in a user-defined module, PROC IML calls the PAUSE statement. This causes the program execution to pause while still inside the module. While the program is paused, you have the opportunity to debug the module, primarily by using PRINT statements to display the values of the local variables in the module. When you "submit other commands," those statements are being executed from within the module, rather than at main scope, which is probably why you say that PROC IML "doesn't seem to understand" the commands.
When a run-time error occurs in a user-defined module in PROC IML, which includes modules in the IMLMLIB library, you have three options:
- Fix the error and resubmit the entire PROC IML program.
- Debug the problem and try to fix it from inside the module. For example, suppose the error occurs while trying to compute some quantity, Z, at Line 2 in the module. While the module is paused, you can assign Z a value and submit the RESUME statement. The program will continue executing from the next statement in the module. That is, from Line 3.
- Submit the STOP statement to leave all modules and return to the main scope of the program. This is especially useful if the cause of the error was a bad parameter value. You can immediately call the module again with different parameter values.
The first option is easy, but if the program has just finished a long-running computation, you might want to try to salvage those computations, rather than restart the program.
Debug, fix, and RESUME
The following statements define a function that evaluates the quantity sqrt(x – 1). If you call the function with a value of x that is less than 1, a run-time error will occur. Let's intentionally cause an error so that the program pauses in the SQRTM1 module:
proc iml; start Sqrtm1(x); y = x - 1; /* Line 1: y is defined inside the module */ z = sqrt(y); /* Line 2 */ s = 17; /* Line 3 */ return( z ); /* Line 4 */ finish; A = 10; /* A is defined outside the module */ B = Sqrtm1(0); /* create run-time error on Line 2 of module */
The SAS Log shows that an error occurred on Line 2 of the module. The Log also says NOTE: Paused in module SQRTM1. The module has executed Line 2 but has not executed Line 3, so you can submit statements that refer to the local variables x and y, which were define before the error occurred. The statements cannot refer to the local variable s, because s has not yet been assigned. The statements also cannot refer to the variable A, because that variable exists only at main scope; the symbol is not known from within the module.
You can convince yourself that the program is paused within the module by submitting the following PRINT statements:
/* the program is paused inside the module */ print x y; /* you can print local vars inside the module */ print A; /* ERROR: this var is not defined inside the module */
If you want, you can assign a value to z and then resume execution of the program. The RESUME statement causes the program to resume execution beginning with Line 3 of the module. If the rest of the program executes without error, the SAS/IML environment returns to main scope, as shown by the following statements:
z = .; /* within module: assign local variable z */ resume; /* resume execution of program at Line 3 */ print A B; /* now at main scope: A and B are defined */
STOP the program and return to main scope
Often it is impractical to "fix" the error from within a module. For example, you might have called a module that called a second module that called a third module, and the error occurred in the third module. Sometimes the wisest course of action is to get out of all the modules and return to the main calling environment. You can use the STOP statement to "pop" the stack of modules and return to main scope. The STOP statement is like a super-duper RETURN statement: it not only returns from the module with the error, but it returns from the complete chain of modules that were being executed. The STOP statement does not exit PROC IML, so use STOP when you want to retain the results from a prior long-running computation.
For example, the following statements once again create a run-time error in the SQRTM1 module. The module execution pauses after the error. If you execute the STOP statement (which supports an optional message statement in SAS/IML 13.1), you will return to the main scope of the program.
B = Sqrtm1(0); /* create run-time error on Line 2 */ stop "Return from the module"; /* SAS/IML 13.1 supports optional message */ print A; /* now at main scope: A is defined */
Debugging in SAS/IML Studio
Errors in the SAS/IML Studio application are handled differently. SAS/IML Studio contains point-and-click features for finding and fixing run-time errors. For an example, see the section "Run-Time Error" in the article "How to find and fix programming errors."
This article describes how to deal with errors in user-defined modules in PROC IML. When a run-time error occurs in a module, the program pauses execution, but does not exit PROC IML. In fact, the program is paused inside the module that experienced the error. You have three choices to handle the error: you can use the QUIT statement to exit PROC IML, you can debug and fix the problem and then use the RESUME statement to continue the program, or you can use the STOP statement to pop out of all modules and return to the main scope of the program.
Pingback: Everything you wanted to know about writing SAS/IML modules - The DO Loop