Conditionally Executing Global Statements
From sasCommunity
The IFC function can be used to conditionally execute global statements, including macro %Put, %Let, and %Include.
To refer to this page use: http://tinyurl.com/25ba6l
Contents |
[edit] Demonstration of Function IFC in Data Step
DATA Testing; attrib Msg length = $ %length(missing); do I = ., 0, 1, -1; Msg = ifc(I,'true','false','missing'); put I= Msg=; end; stop; run;
log:
3 DATA Testing; 4 attrib Msg length = $ %length(missing); 5 do I = ., 0, 1; 6 Msg = ifc(I,'true','false','missing'); 7 put I= Msg=; 8 end; 9 stop; 10 run; I=. Msg=missing I=0 Msg=false I=1 Msg=true I=-1 Msg=true
[edit] Open Code Macro Statements
options source2;
%Put
%sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2
,source2: echo includes
,nosource2: no echo of includes
) );
options nosource2;
%Put
%sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2
,source2: echo includes
,nosource2: no echo of includes
) );
%Let Mvar =
%sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2
,source2: echo includes
,nosource2: no echo of includes
) );
%Put Mvar: &Mvar.;
log:
2 options source2; 3 %Put 4 %sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2 5 ,source2: echo includes 6 ,nosource2: no echo of includes 7 ) ); source2: echo includes 8 9 options nosource2; 10 11 %Put 12 %sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2 13 ,source2: echo includes 14 ,nosource2: no echo of includes 15 ) ); nosource2: no echo of includes 16 17 %Let Mvar = 18 %sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2 19 ,source2: echo includes 20 ,nosource2: no echo of includes 21 ) ); 22 %Put Mvar: &Mvar.; Mvar: nosource2: no echo of includes
[edit] Executing Global Macro Statements
Take a look at the obvious.
options source2;
%sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2
,%put true*;
,%put *false;
))
log: Ooops!
2 options source2; 3 %sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2 4 ,%put true*; true* 5 ,%put *false; *false 6 ));
[edit] Using Nrstr to Delay Execution of Macro Statements
Fehd and Carpenter review the timing issues of using %nrstr to delay execution of macro statements until they are popped off the stack.
options source2;
%sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2
,%nrstr(%put true*;)
,%nrstr(%put *false;)
));
options nosource2;
%sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2
,%nrstr(%put true*;)
,%nrstr(%put *false;)
));
log:
2 options source2; 3 %sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2 4 ,%nrstr(%put true*;) 5 ,%nrstr(%put *false;) 6 )); true* 7 options nosource2; 8 %sysfunc(ifc(%sysfunc(getoption(source2)) eq SOURCE2 9 ,%nrstr(%put true*;) 10 ,%nrstr(%put *false;) 11 )); *false
The above code can be used to conditionally execute %includes.
Note This code can be used to do Assertions.
[edit] Assertions
Reference: Automated Testing and Real-time Event Management
http://www2.sas.com/proceedings/sugi29/228-29.pdf
- boolean: zero, one, or ge one
- exist(Data)
- fexist(FileRef)
- nobs(Data)
- nvars(Data)
- comparison:
- &NobsData. eq &NobsFreq.
- &Nobs1. and &Nobs2.
- existence:
- exist(data),
- fexist(fileref)
[edit] Assert Exist Data
OnLine Doc: exist
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210903.htm
%sysfunc(ifc(%sysfunc(exist(&Data.))
,%nrstr(%Put Note2: Data &Data. exists;)
,%nrstr(%Put Note3: not exist &Data.;
endSAS;) ))
* assert-exist-data-Test; options source2; %let data = sashelp.class; %Include Project(assert-exist-data); %let data = sashelp.classX;
[edit] Assert FExist FileRef
OnLine Doc: fexist
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210817.htm
%sysfunc(ifc(%sysfunc(fexist(&FileRef.))
,%nrstr(%Put Note2: FileRef &FileRef. exists;)
,%nrstr(%Put Note3: not exist &FileRef.;
endSAS;) ))
* assert-fexist-fileref-Test; options source2; %let Fileref = SiteIncl; %Include Project(assert-fexist-fileref); %let Fileref = SiteInc; %Include Project(assert-fexist-fileref);
[edit] Assert Exist FileNameExt
OnLine Doc: fileexist
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210912.htm
%sysfunc(ifc(%sysfunc(fileexist(&FileNameExt.))
,%nrstr(%Put Note2: FileNameExt &FileNameExt. exists;)
,%nrstr(%Put Note3: not exist &FileNameExt.;
endSAS;) ))
* assert-fileexist-filename-Test; options source2; %let Fileref = SiteIncl; %Include Project(assert-fileexist-filename); %let Fileref = SiteInc; %Include Project(assert-fileexist-filename);
[edit] Assert FileRef
The fileref function is an exception to the returns boolean rule.
- -1: A negative return code indicates that the fileref exists
but the physical file associated with the fileref does not exist.
- 0 : A value of zero indicates that
the fileref and external file both exist.
- +1: A positive value indicates that the fileref is not assigned.
OnLine Doc for Windows:
http://support.sas.com/documentation/cdl/en/hostwin/59544/HTML/default/win-func-fileref.htm
%sysfunc(ifc(%sysfunc(fileref(&FileRef.)) eq 0
,%nrstr(%Put Note2: FileRef &FileRef. exists but file not;)
,%nrstr(%Put Note3: not exist &FileRef.;
endSAS;) ))
see OnLine Doc of Windows finfo function for a usage example.
http://support.sas.com/documentation/cdl/en/hostwin/59544/HTML/default/win-func-finfo.htm
* assert-fileref-Test; * see OnLine Doc of finfo function for usage example; options source2; filename ThisFile 'assert-fileref-Test.sas'; %let Fileref = ThisFile; %Include Project(assert-fileref); filename NextFile 'assert-fileref-Test.txt'; %let Fileref = NextFile; %Include Project(assert-fileref);
[edit] Assert Nobs or Nvars
OnLine Doc: open
OnLine Doc: attrn: nobs and nvars
OnLine Doc: close
%let dsid = %sysfunc(open(&Data. ));
%let Nobs = 0;
%let Nvars = 0;
%sysfunc(ifc(&DsId.
,%nrstr(%let Nobs = %sysfunc(attrn(&dsid.,nobs ));
%let Nvars = %sysfunc(attrn(&dsid.,nvars));)
,%nrstr() ))
%let rc = %sysfunc(close(&dsid.));
%sysfunc(ifc(&Nobs.
,%nrstr(%Put Note2: Data &Data. available Nobs: &Nobs.;
%Put Note2: Data &Data. available Nvars: &Nvars.;
)
,%nrstr(%Put %sysfunc(sysmsg());
endSAS;) ))
options source2; %Let Data = sashelp.Class; %Include Project(assert-nobs); %Let Data = sashelp.ClassX; %Include Project(assert-nobs);
[edit] Branching
A version of this trick was shown in: The Writing for Reading SAS ® Style Sheet: Tricks, Traps & Tips from SAS-L’s Macro Maven
http://www2.sas.com/proceedings/sugi25/25/ad/25p038.pdf
This example shows testing for nobs and branching on Nobs
- ge 0
- eq 0
* cond-inc-which;
options source2;
%Let Data = sashelp.Class;
%Let Data = sashelp.ClassX;
%let dsid = %sysfunc(open(&Data. ));
%let Nobs =
%sysfunc(ifc(&DsId.
,%nrstr( %sysfunc(attrn(&dsid.,nobs));
%let rc = %sysfunc(close(&dsid.)); )
,%nrstr(0) ));
%sysfunc(ifc(&Nobs.
,%nrstr(%Include Project(cond-inc-1);)
,%nrstr(%Include Project(cond-inc-0);) ))
%Put Note2: file is cond-inc-0;
%Put Note2: file is cond-inc-1;
--macro maven == the radical programmer 16:23, 7 March 2008 (EST)
[edit] Be Careful of Characters that Require Quoting
This technique does not handle special characters that require macro quoting well. Consider the following example.
Set up two macro variables to be compared and then compare them using this technique:
1 %let value = a/b;
2 %let compare = some other value;
3 %put %sysfunc(ifc(&value = &compare
4 ,Equal
5 ,Different));
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: a/b = some other value
ERROR: Argument 1 to function IFC referenced by the %SYSFUNC or %QSYSFUNC macro function is not
a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC argument list. Execution
of %SYSCALL statement or %SYSFUNC or %QSYSFUNC function reference is terminated.
Since the values include the / character, a numeric operation is implied. To address this in the macro language, one would use a macro quoting function:
6 %put %sysfunc(ifc(%bquote(&value) = %bquote(&compare)
7 ,Equal
8 ,Different));
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: a/b = some other value
ERROR: Argument 1 to function IFC referenced by the %SYSFUNC or %QSYSFUNC macro function is not
a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC argument list. Execution
of %SYSCALL statement or %SYSFUNC or %QSYSFUNC function reference is terminated.
Note how the error still occurs.
[edit] An IIF Macro
The following macro is referenced in the book Building Web Applications with SAS/IntrNet: A Guide to the Application Dispatcher as a way of doing such comparisons in Open Code.
9 %macro iif 10 (cond, /* logical expression to evaluate */ 11 positive, /* text to return if expression true */ 12 negative /* text to return if expression false */ 13 ); 14 /*-------------------------------------------------------------------*/ 15 /* Building Web Applications with SAS/IntrNet(R): */ 16 /* A Guide to the Application Dispatcher */ 17 /* by Don Henderson, Henderson Consulting Services */ 18 /* Copyright(c) 2006 by SAS Institute Inc., Cary, NC, USA */ 19 /* SAS Publications order */ 20 /* ISBN 978-1-59994-189-9 */ 21 /*-------------------------------------------------------------------*/ 22 /* rest of comment blocked snipped */ 23 24 %if &cond %then %do; 26 %unquote(&positive) 27 %end; 28 %else %do; 30 %unquote(&negative) 31 %end; 32 33 %mend IIF;
Note that when the values are not quoted, we get the same error with the IIF macro:
35 %put %iif(&value = &compare
36 ,Equal
37 ,Different);
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: &cond
ERROR: The macro IIF will stop executing.
But when quoted, we get the correct behavior as one would expect when using macro quoting functions.
38 %put %iif(%bquote(&value) = %bquote(&compare) 39 ,Equal 40 ,Different); Different
- This page was last modified 2008-Mar-19.
- This page has been accessed 1,525 times as of 2008-Jul-09.
