As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.


Here are some tips for How to share your SAS knowledge with your professional network.


Difference between revisions of "Conditionally Executing Global Statements"

From sasCommunity
Jump to: navigation, search
m (changed category)
(added sub.section Tricks w/Macro Variable Substitution changed pre to source lang=sas in section Assertions)
 
Line 152: Line 152:
  
 
Note This code can be used to do [[Assertions]].
 
Note This code can be used to do [[Assertions]].
 +
 +
=== Trick with Macro Variable Resolution ===
 +
All macros are ''resolved''.
 +
For macro variables, ''resolved'' means ''substituting''.
 +
For macro definitions, ''resolved'' means ''expanding''.
 +
 +
This trick involves in-line expansion of a conditionally-executed string.
 +
 +
Knowledge to remember:
 +
* %nrstr (no-rescan-this-is-a-string) function disables substitution of macro variable reference(s) (&mvar)
 +
and expansion of macro definition(s) (%verb(data=)).
 +
* %unquote function directs the macro language to put the string in the token-resolution stream;
 +
i.e. macro variables reference and definitions are ''resolved''.
 +
 +
<source lang="sas">
 +
%let macro_catalog=work.sasmacr;
 +
%sysfunc(ifc(  %sysfunc(cexist(&macro_catalog))
 +
    ,%nrstr(%put exist catalog(&macro_catalog);)
 +
,%nrstr(%put not exist catalog(&macro_catalog);),))
 +
 +
%macro test1(data=sashelp.class);
 +
*noop;
 +
%mend;
 +
run;
 +
%put echo %sysfunc(ifc(%sysfunc(cexist(&macro_catalog))
 +
        ,,%nrstr(not),)) exist catalog(&macro_catalog);
 +
 +
**** macros compiled and stored;
 +
%put mstored=%sysfunc(getoption(mstored));
 +
%let sasmstore=%sysfunc(getoption(sasmstore));
 +
%put &=sasmstore;
 +
 +
* if not already allocated;
 +
*libname library '.';
 +
options mstored sasmstore=library;
 +
%put mstored=%sysfunc(getoption(mstored));
 +
%let sasmstore=%sysfunc(getoption(sasmstore));
 +
%put &=sasmstore;
 +
 +
%let exist = cexist;*catalog;
 +
%let object = &sasmstore..sasmacr;
 +
%let exist_note = %nrstr(echo
 +
%sysfunc(ifc(%sysfunc(&exist(&object))
 +
        ,,%nrstr(not),)) exist object(&object));
 +
 +
%put %unquote(&exist_note);
 +
 +
%macro test2(data=sashelp.class)/store;
 +
*noop;
 +
%mend;
 +
 +
%put %unquote(&exist_note);
 +
 +
%let object = work.formats;
 +
%put %unquote(&exist_note);
 +
%let object = library.formats;
 +
%put %unquote(&exist_note);
 +
proc format library=library;
 +
value demo 1='one';
 +
run;
 +
%put %unquote(&exist_note);
 +
 +
 +
%let exist = exist;*data set;
 +
%let object = sashelp.class;
 +
%put %unquote(&exist_note);
 +
%let object = work.class;
 +
%put %unquote(&exist_note);
 +
</source>
 +
 +
The log is left as an exercise for the reader.
  
 
== Assertions ==
 
== Assertions ==
Line 177: Line 248:
 
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210903.htm
 
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210903.htm
  
<pre>
+
<source lang="sas">
 
%sysfunc(ifc(%sysfunc(exist(&Data.))
 
%sysfunc(ifc(%sysfunc(exist(&Data.))
 
             ,%nrstr(%Put Note2: Data &Data. exists;)
 
             ,%nrstr(%Put Note2: Data &Data. exists;)
 
             ,%nrstr(%Put Note3: not exist &Data.;
 
             ,%nrstr(%Put Note3: not exist &Data.;
 
                     endSAS;) ))
 
                     endSAS;) ))
</pre>
+
</source>
  
<pre>
+
<source lang="sas">
 
* assert-exist-data-Test;
 
* assert-exist-data-Test;
 
options source2;
 
options source2;
Line 190: Line 261:
 
%Include Project(assert-exist-data);
 
%Include Project(assert-exist-data);
 
%let data = sashelp.classX;
 
%let data = sashelp.classX;
</pre>
+
</source>
  
 
=== Assert FExist FileRef ===
 
=== Assert FExist FileRef ===
Line 198: Line 269:
 
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210817.htm
 
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210817.htm
  
<pre>
+
<source lang="sas">
 
%sysfunc(ifc(%sysfunc(fexist(&FileRef.))
 
%sysfunc(ifc(%sysfunc(fexist(&FileRef.))
 
             ,%nrstr(%Put Note2: FileRef &FileRef. exists;)
 
             ,%nrstr(%Put Note2: FileRef &FileRef. exists;)
 
             ,%nrstr(%Put Note3: not exist &FileRef.;
 
             ,%nrstr(%Put Note3: not exist &FileRef.;
 
                     endSAS;) ))
 
                     endSAS;) ))
</pre>
+
</source>
  
<pre>
+
<source lang="sas">
 
* assert-fexist-fileref-Test;
 
* assert-fexist-fileref-Test;
 
options source2;
 
options source2;
Line 212: Line 283:
 
%let Fileref = SiteInc;
 
%let Fileref = SiteInc;
 
%Include Project(assert-fexist-fileref);
 
%Include Project(assert-fexist-fileref);
</pre>
+
</source>
  
 
=== Assert Exist FileNameExt ===
 
=== Assert Exist FileNameExt ===
Line 220: Line 291:
 
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210912.htm
 
http://support.sas.com/documentation/cdl/en/lrdict/59540/HTML/default/a000210912.htm
  
<pre>
+
<source lang="sas">
 
%sysfunc(ifc(%sysfunc(fileexist(&FileNameExt.))
 
%sysfunc(ifc(%sysfunc(fileexist(&FileNameExt.))
 
             ,%nrstr(%Put Note2: FileNameExt &FileNameExt. exists;)
 
             ,%nrstr(%Put Note2: FileNameExt &FileNameExt. exists;)
 
             ,%nrstr(%Put Note3: not exist &FileNameExt.;
 
             ,%nrstr(%Put Note3: not exist &FileNameExt.;
 
                     endSAS;) ))
 
                     endSAS;) ))
</pre>
+
</source>
  
<pre>
+
<source lang="sas">
 
* assert-fileexist-filename-Test;
 
* assert-fileexist-filename-Test;
 
options source2;
 
options source2;
Line 234: Line 305:
 
%let Fileref = SiteInc;
 
%let Fileref = SiteInc;
 
%Include Project(assert-fileexist-filename);
 
%Include Project(assert-fileexist-filename);
</pre>
+
</source>
  
 
=== Assert FileRef ===
 
=== Assert FileRef ===
Line 250: Line 321:
 
http://support.sas.com/documentation/cdl/en/hostwin/59544/HTML/default/win-func-fileref.htm
 
http://support.sas.com/documentation/cdl/en/hostwin/59544/HTML/default/win-func-fileref.htm
  
<pre>
+
<source lang="sas">
 
%sysfunc(ifc(%sysfunc(fileref(&FileRef.)) eq 0
 
%sysfunc(ifc(%sysfunc(fileref(&FileRef.)) eq 0
 
             ,%nrstr(%Put Note2: FileRef &FileRef. exists but file not;)
 
             ,%nrstr(%Put Note2: FileRef &FileRef. exists but file not;)
 
             ,%nrstr(%Put Note3: not exist &FileRef.;
 
             ,%nrstr(%Put Note3: not exist &FileRef.;
 
                     endSAS;) ))
 
                     endSAS;) ))
</pre>
+
</source>
  
 
see OnLine Doc of Windows finfo function for a usage example.
 
see OnLine Doc of Windows finfo function for a usage example.
Line 261: Line 332:
 
http://support.sas.com/documentation/cdl/en/hostwin/59544/HTML/default/win-func-finfo.htm
 
http://support.sas.com/documentation/cdl/en/hostwin/59544/HTML/default/win-func-finfo.htm
  
<pre>
+
<source lang="sas">
 
* assert-fileref-Test;
 
* assert-fileref-Test;
 
* see OnLine Doc of finfo function for usage example;
 
* see OnLine Doc of finfo function for usage example;
Line 271: Line 342:
 
%let Fileref = NextFile;
 
%let Fileref = NextFile;
 
%Include Project(assert-fileref);
 
%Include Project(assert-fileref);
</pre>
+
</source>
  
 
=== Assert LibRef ===
 
=== Assert LibRef ===
Line 279: Line 350:
 
* #0: failure
 
* #0: failure
  
<pre>
+
<source lang="sas">
 
%Let Libref = LIB5;
 
%Let Libref = LIB5;
 
%Let Libref = sashelp;
 
%Let Libref = sashelp;
Line 287: Line 358:
 
             ,%nrstr(%Put note: &Libref. exists;)
 
             ,%nrstr(%Put note: &Libref. exists;)
 
         )  )
 
         )  )
</pre>
+
</source>
  
 
=== Assert Nobs or Nvars ===
 
=== Assert Nobs or Nvars ===
Line 297: Line 368:
 
OnLine Doc: close
 
OnLine Doc: close
  
<pre>
+
<source lang="sas">
 
%let dsid  = %sysfunc(open(&Data. ));
 
%let dsid  = %sysfunc(open(&Data. ));
 
%let Nobs  = 0;
 
%let Nobs  = 0;
Line 312: Line 383:
 
             ,%nrstr(%Put %sysfunc(sysmsg());
 
             ,%nrstr(%Put %sysfunc(sysmsg());
 
                     endSAS;) ))
 
                     endSAS;) ))
</pre>
+
</source>
  
<pre>
+
<source lang="sas">
 
options source2;
 
options source2;
 
%Let Data = sashelp.Class;
 
%Let Data = sashelp.Class;
Line 320: Line 391:
 
%Let Data = sashelp.ClassX;
 
%Let Data = sashelp.ClassX;
 
%Include Project(assert-nobs);
 
%Include Project(assert-nobs);
</pre>
+
</source>
  
 
=== Branching ===
 
=== Branching ===
Line 335: Line 406:
 
* eq 0
 
* eq 0
  
<pre>
+
<source lang="sas">
 
* cond-inc-which;
 
* cond-inc-which;
 
options source2;
 
options source2;
Line 349: Line 420:
 
             ,%nrstr(%Include Project(cond-inc-1);)
 
             ,%nrstr(%Include Project(cond-inc-1);)
 
             ,%nrstr(%Include Project(cond-inc-0);) ))
 
             ,%nrstr(%Include Project(cond-inc-0);) ))
</pre>
+
</source>
  
<pre>
+
<source lang="sas">
 
%Put Note2: file is cond-inc-0;
 
%Put Note2: file is cond-inc-0;
</pre>
+
</source>
  
<pre>
+
<source lang="sas">
 
%Put Note2: file is cond-inc-1;
 
%Put Note2: file is cond-inc-1;
</pre>
+
</source>
  
 
--macro maven == the radical programmer 16:23, 7 March 2008 (EST)
 
--macro maven == the radical programmer 16:23, 7 March 2008 (EST)
 
  
 
== Be Careful of Characters that Require Quoting ==
 
== Be Careful of Characters that Require Quoting ==

Latest revision as of 08:17, 9 June 2015

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

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

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


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                      ));


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.

Trick with Macro Variable Resolution

All macros are resolved. For macro variables, resolved means substituting. For macro definitions, resolved means expanding.

This trick involves in-line expansion of a conditionally-executed string.

Knowledge to remember:

  •  %nrstr (no-rescan-this-is-a-string) function disables substitution of macro variable reference(s) (&mvar)

and expansion of macro definition(s) (%verb(data=)).

  •  %unquote function directs the macro language to put the string in the token-resolution stream;

i.e. macro variables reference and definitions are resolved.

%let macro_catalog=work.sasmacr;
%sysfunc(ifc(  %sysfunc(cexist(&macro_catalog))
    ,%nrstr(%put exist catalog(&macro_catalog);)
,%nrstr(%put not exist catalog(&macro_catalog);),))
 
%macro test1(data=sashelp.class);
*noop;
%mend;
run;
%put echo %sysfunc(ifc(%sysfunc(cexist(&macro_catalog))
        ,,%nrstr(not),)) exist catalog(&macro_catalog);
 
**** macros compiled and stored;
%put mstored=%sysfunc(getoption(mstored));
%let sasmstore=%sysfunc(getoption(sasmstore));
%put &=sasmstore;
 
* if not already allocated;
*libname library '.';
options mstored sasmstore=library;
%put mstored=%sysfunc(getoption(mstored));
%let sasmstore=%sysfunc(getoption(sasmstore));
%put &=sasmstore;
 
%let exist = cexist;*catalog;
%let object = &sasmstore..sasmacr;
%let exist_note = %nrstr(echo
%sysfunc(ifc(%sysfunc(&exist(&object))
        ,,%nrstr(not),)) exist object(&object));
 
%put %unquote(&exist_note);
 
%macro test2(data=sashelp.class)/store;
*noop;
%mend;
 
%put %unquote(&exist_note);
 
%let object = work.formats;
%put %unquote(&exist_note);
%let object = library.formats;
%put %unquote(&exist_note);
proc format library=library;
value demo 1='one';
run;
%put %unquote(&exist_note);
 
 
%let exist = exist;*data set;
%let object = sashelp.class;
%put %unquote(&exist_note);
%let object = work.class;
%put %unquote(&exist_note);

The log is left as an exercise for the reader.

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)

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;

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);

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);

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);

Assert LibRef

The libref functions returns:

  • 0: success == exists
  • #0: failure
%Let Libref = LIB5;
%Let Libref = sashelp;
 
%sysfunc(ifc(%sysfunc(libref(&Libref.))
            ,%nrstr(%Put note: &Libref. not exists;)
            ,%nrstr(%Put note: &Libref. exists;)
         )  )

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);

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)

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.

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

References

See also: Assertions