Hello Folks,
running this code:
%macro debug;
%LET _doDebug = no;
%IF condition &_doDebug >= 1 %THEN %DO;
%PUT &=_doDebug;
%PUT PLEASE DO DEBUG THIS CODE!;
%END;
%ELSE %DO;
%PUT &=_doDebug;
%PUT DO NOT DEBUG!;
%END;
%mend;
%debug
I would expect the macro to abort with an error stating
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
condition &_doDebug >= 1
ERROR: The macro DEBUG will stop executing.
However, it runs perferctly fine, although with an outcome that is not desired, namly to set the if condition to TRUE:
MLOGIC(DEBUG): %IF-Bedingung condition &_doDebug >= 1 ist TRUE
Why does SAS this? How can SAS equate a character expression with a numeric expression?
Also, wenn assigning the value "do not debug" to the macro variable "_doDebug
" the macro does, what I expected:
30 %macro debug;
31
32 %LET _doDebug = do not debug;
33
34 %IF condition &_doDebug >= 1 %THEN %DO;
35
36 %PUT &=_doDebug;
37 %PUT PLEASE DO DEBUG THIS CODE!;
38
39 %END;
40
41
42 %ELSE %DO;
43 %PUT &=_doDebug;
44 %PUT DO NOT DEBUG!;
45 %END;
46
47 %mend;
48
49 %debug
MLOGIC(DEBUG): Ausführung beginnt.
MLOGIC(DEBUG): %LET (Variablenname ist _DODEBUG)
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
condition &_doDebug >= 1
ERROR: The macro DEBUG will stop executing.
MLOGIC(DEBUG): Ausführung wird beendet.
Can someone enlighten me?
As others have explained, macro language is perfectly capable of making this comparison:
%if c >= 1 %then %do;
There is an order to all characters (different for ASCII-based systems vs. EBCDIC), and macro language evaluates "c" and "1" as characters.
When you change the comparison by adding the word "not" it affects how macro language evaluates your request:
%LET _doDebug = do not debug;
%IF condition &_doDebug >= 1 %THEN %DO;
Now macro language sees:
%IF condition do not debug >= 1 %then %DO;
While I haven't tested to be sure, the word NOT affects the comparison, forcing that part of the logic to be evaluated first. In effect, macro language evaluates:
%IF condition do (not (debug >= 1)) %then %DO;
By evaluating the innermost portion of the comparison first, macro language next sees one of these (depending on whether the comparison is true or false):
%IF condition do 1 %then %DO;
%IF condition do 0 %then %DO;
That's the point where macro language gets confused and thinks you have entered an illegal %IF condition.
I'm not sure this is particularly useful, but it should explain the second part of your question about why you get an error message when you add NOT into the mix.
The macro processor is simply a text processor. So
%IF condition &_doDebug >= 1 %THEN %DO;
resolves to comparing text string "condition no" to be greater than or equal to the text string "1", which is true when comparing text strings.
Hi @PaigeMiller ,
you are right: the macro processor is just a text processor. But how can this text processor evaluate a comparisson between two strings ? If I understand you correctly, then this processor does not recognize the string "1" as a number, but rather as a string of length 1. Also it recognizes the string "no" as a string of length 2.
Does the condition resolve to TRUE because it compares THE LENGTH of the strings, namly 2>= 1 and therefore resolves to TRUE?
The length of the string is not what is being compared. The content of the strings themselves are being compared, using an alphabetical sorting to do the comparison.
The string "condition no" is greater than the string "1" when compared alphabetically.
The "left" part of the comparison is not the 2-character string "no", but the 12-character string "condition no".
Anyway, since all letters (uppercase and lowercase) come after the digits in the ASCII table, this comparison will always resolve to true, because "c" > "1".
As others have explained, macro language is perfectly capable of making this comparison:
%if c >= 1 %then %do;
There is an order to all characters (different for ASCII-based systems vs. EBCDIC), and macro language evaluates "c" and "1" as characters.
When you change the comparison by adding the word "not" it affects how macro language evaluates your request:
%LET _doDebug = do not debug;
%IF condition &_doDebug >= 1 %THEN %DO;
Now macro language sees:
%IF condition do not debug >= 1 %then %DO;
While I haven't tested to be sure, the word NOT affects the comparison, forcing that part of the logic to be evaluated first. In effect, macro language evaluates:
%IF condition do (not (debug >= 1)) %then %DO;
By evaluating the innermost portion of the comparison first, macro language next sees one of these (depending on whether the comparison is true or false):
%IF condition do 1 %then %DO;
%IF condition do 0 %then %DO;
That's the point where macro language gets confused and thinks you have entered an illegal %IF condition.
I'm not sure this is particularly useful, but it should explain the second part of your question about why you get an error message when you add NOT into the mix.
Thank you all, guys.
I really did learn something today!
Now I am keen on telling my coworkers! I'm sure, they are as surprised as I was to learn that
%if c >= 1 %then %do;
is a perfectly fine expression in SAS 🙂
Cheers,
FK1
@FK1 wrote:
Thank you all, guys.
I really did learn something today!
Now I am keen on telling my coworkers! I'm sure, they are as surprised as I was to learn that
%if c >= 1 %then %do;
is a perfectly fine expression in SAS 🙂
Cheers,
FK1
It's correct syntax, but nonsense semantically (as it will always be true).
PS in a data step,
if c >= 1
compares the value stored in variable c with the literal value 1, which makes a lot of sense.
@FK1 wrote:
Thank you all, guys.
I really did learn something today!
Now I am keen on telling my coworkers! I'm sure, they are as surprised as I was to learn that
%if c >= 1 %then %do;
is a perfectly fine expression in SAS 🙂
Cheers,
FK1
I think the point is that macro variables and values can be compared alphabetically, so that you can find text strings that come earlier or later in the alphabet. Which of course could have many real-world uses. Here's a trivial example:
%let a=vanilla;
%let b=chocolate;
%if &a > &b %then %do; %put TRUE; %end;
%else %do; %put FALSE; %end;
But if your example is comparing a text string the the constant value 1, well I don't see any real-world uses here.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.