I have a SUBROUTINE with arguments that get validated. If the validation fails I would like to exit the subroutine instead of having deeply nested if/then
subroutine xyzzy(file1 $, file2 $, rc, message $)
outargs result, message;
if missing (file1) then do ;
message = 'Argument 1 can not be blank.' ;
rc = -1 ;
<EXIT_STATEMENT> ;
end ;
...
endsub ;
quit ;
Don't really want to have to code. Exit statements such as QUIT; RETURN; EXIT; don't work. Either wrong context for the statement, or invalid compilation.
subroutine xyzzy(file1 $, file2 $, rc, message $)
outargs rc, message;
rc = 0 ;
if not <validation-1-criteria> then do ;
message = "<validation-1-fail-message>" ;
rc = -1 ;
end ;
if rc = 0 and not <validation-2-criteria> then do ;
message = "<validation-2-fail-message>" ;
rc = -1 ;
end ;
...
endsub ;
quit ;
Things can go gnarly nested if's because there will be multiple dynamic fileref assignments, fopens, etc...
You can use the LEAVE statement to exit a DO loop or SELECT group prematurely based on a condition. If you are using LIBNAME, FILENAME, DOPEN, FOPEN, or other functions that can lock resources, you might consider instead using a GOTO statement to jump to an exit routine that includes the appropriate DCLOSE, FCLOSE, FILENAME or LIBNAME functions to release the lock on the files for a graceful exit from the subroutine.
You can use the LEAVE statement to exit a DO loop or SELECT group prematurely based on a condition. If you are using LIBNAME, FILENAME, DOPEN, FOPEN, or other functions that can lock resources, you might consider instead using a GOTO statement to jump to an exit routine that includes the appropriate DCLOSE, FCLOSE, FILENAME or LIBNAME functions to release the lock on the files for a graceful exit from the subroutine.
The LEAVE statement was not appropriate for my situation. However, the old standby GOTO works. I hadn't seen GOTO listed in the FCMP reference, but the docs state:
Writing Program Statements
The program-statements section of the program is a series of DATA step and or FCMP statements that describe the work to be done by the function or CALL routine. Most DATA step statements and functions are accessible from PROC FCMP routines.
...
Good advice to check and close all resource handles that might have been opened. Resource handles obtained in FCMP user functions or subroutines can be passed back to the caller as part of a legitimate coding/framework architecture, so are not auto freed.
My DATA Step habit is to let the step do it's auto close and deletion of open resources.
There are probably ways, but perhaps for parameter validation is not needed, or wanted.
You should validate ALL of the inputs and report ALL of the issues detected and then exit so that the user does not end up fixing the problem with the first parameter only to have the call fail again because the second parameter also had a problem but you didn't tell them.
Something like:
rc=0;
if missing (file1) then do ;
message = 'Argument 1 can not be blank.' ;
rc = -1 ;
end ;
if missing(file2) then do;
message = catx(';',message,'Argument 2 cannot by blank.');
rc=-1;
end;
if rc=0 then do;
... body of function ...
end;
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.