I'm trying to make a simple macro that checks whether a specific macro variable is either missing or does not exist. Normally, this would require two statements: a %symexist
, and if it does exist, additional logic to detect whether it's a null value. The below code combines all of that into one.
%macro isnull(macvar);
%sysevalf(%superq(%superq(macvar)) NE %str(), boolean);
%mend isnull;
Problem
I cannot use %isNull()
in a %if
statement, because the returned value always seems to be a character. This behavior differs if it's in open code or within a macro itself.
What I've tried
I've narrowed it down to the macro not resolving as a numeric value. I've tried everything from enclosing it with %sysfunc(putn())
to %cmpres()
to %sysfunc(compress())
. If it's in open code, it is numeric. If it's in another macro, it's character. You can see it with this code:
/* Miss2 resolves incorrectly as character */
%macro check;
%let miss1=%sysevalf(%superq(asdf) =, boolean);
%let miss2=%isNull(asdf);
%put Miss1: %datatyp(&miss1);
%put Miss2: %datatyp(&miss2);
%mend;
%check;
/* Miss2 resolves correctly as numeric */
%let miss1=%sysevalf(%superq(asdf) =, boolean);
%let miss2=%isNull(asdf);
%put Miss1: %datatyp(&miss1);
%put Miss2: %datatyp(&miss2);
Want
I want to be able to use this in a %if
statement to check whether a macro both exists and is not blank simultaneously.
%macro foo;
%if(%isNull(sysuserid) = 1) %then %put sysuserid exists;
%if(%isNull(asdffdsa) = 0) %then %put asdffdsa does not exist;
%if(%isNull(sysuserid) > 0) %then %put this should resolve;
%if(%isNull(asdffdsa) > 0) %then %put this should not resolve;
%mend;
%foo;
The problem you have here is that your macro has a semicolon in it. See this:
174 %macro check;
175 %let miss1=%sysevalf(%superq(asdf) NE %str(), boolean);
176 %let miss2=%missm(asdf);
177
178 %put &miss1. Miss1: %datatyp(&miss1);
179 %put &miss2. Miss2: %datatyp(%unquote(&miss2));
180 %mend;
181 %check;
WARNING: Apparent symbolic reference ASDF not resolved.
WARNING: Apparent symbolic reference ASDF not resolved.
0 Miss1: NUMERIC
0; Miss2: CHAR
Note the ;
? Compile this instead:
%macro missm(macvar);
%sysevalf(%superq(%superq(macvar)) NE %str(), boolean)
%mend missm;
and you get:
185 %macro check;
186 %let miss1=%sysevalf(%superq(asdf) NE %str(), boolean);
187 %let miss2=%missm(asdf);
188
189 %put &miss1. Miss1: %datatyp(&miss1);
190 %put &miss2. Miss2: %datatyp(%unquote(&miss2));
191 %mend;
192 %check;
WARNING: Apparent symbolic reference ASDF not resolved.
WARNING: Apparent symbolic reference ASDF not resolved.
0 Miss1: NUMERIC
0 Miss2: NUMERIC
I'll also add that I think you should not skip the %symexist
. You get a warning in the log the way you're doing it here, that's easily avoided.
%macro missm(macvar);
%if %symexist(&macvar.) %then
%sysevalf(%superq(%superq(macvar)) NE , boolean)
%else
0
%mend missm;
You'll also note I remove your unnecessary %str()
which doesn't really do anything. See Chang Chung's seminal paper, Is This Macro Parameter Blank, for why (and for some more great information, if you haven't already read it).
Finally - I think I would suggest renaming your macro and/or reversing the direction. %if %missm
says to me 'if this macro variable is missing', which is the opposite of what you're telling: TRUE is returned if it is NOT missing. %missm
should return true for EQ [blank], or NOT %symexist
; it should return false for [defined and contains a value].