BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Bill3
Fluorite | Level 6

for example: Step1: %let tab=3; %macro test(); %if 1<&tab.<4 %then %do; %put it worked; %end; %mend test; %test; Step2: when i modified "%let tab =4; it still prints "it worked".

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

In the language of normal SAS code you can abbreviate an expression in the form:

(A op1 B) and (B op2 C)

By removing the AND and the duplicate value/variable to get:

A op1 B op2 C

But the language used by the MACRO PROCESSOR does NOT support that abbreviated syntax.

 

If you have a question about how to expand an abbreviated expression you can use it in a WHERE statement and SAS will echo to restructured syntax in the log.

1    data want;
2      set sashelp.class;
3      where age < height < weight ;
4    run;

NOTE: There were 18 observations read from the data set SASHELP.CLASS.
      WHERE (age<height) and (height<weight);
NOTE: The data set WORK.WANT has 18 observations and 5 variables.
NOTE: DATA statement used (Total process time):
      real time           0.07 seconds
      cpu time            0.01 seconds

View solution in original post

7 REPLIES 7
Patrick
Opal | Level 21

I couldn't find it in the documentation but using macro language you can't combine comparison operators the way you did. 

Below syntax will return what you're after.

%macro test(tab);
/*  %if %eval(1<&tab.<4) %then*/
  %if 1<&tab. and &tab.<4 %then
    %do;
      %put TRUE;
    %end;
  %else %put FALSE;
%mend test;

%test(3);
%test(4);
Bill3
Fluorite | Level 6
sorry, i just want to combine these two operators.
mkeintz
PROC Star

Unlike the IF clause in regular SAS data step, the %IF macro statement processes from left to right, which means the expression

 

 %IF 1<&tab.<4  

first evaluates the 1<&tab component.   When macrovar &TAB equals 3, this component resolves to 1 (for true).  When macrovar &TAB is, say 0, this component resolves to 0 (for false).

 

Then it tests whether that resolved value is less than 4, which is also true (because both 0 and 1 are <4).  In fact, for any &TAB value, the %IF 1<&tab.<4 macro test will always be true.  

 

 

 

But as you no doubt know, this is NOT the behavior of the non-macro IF statement, which imputes an implicit AND operator when you have the if value1 relop value2 relop value3 structure (where "relop" means relational operator).  So the expression

if  1<%tab.<4

is interpreted as 

if  1<&tab.  AND &tab<4
--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Bill3
Fluorite | Level 6
It seems quite reasonable. So there's no way to combine these two relop in %if?
mkeintz
PROC Star

@Bill3 wrote:
It seems quite reasonable. So there's no way to combine these two relop in %if?

I believe you will have to insert the AND operator, as in:

  %if 1<&tab.  AND &tab.<4 %then %do; 

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Tom
Super User Tom
Super User

In the language of normal SAS code you can abbreviate an expression in the form:

(A op1 B) and (B op2 C)

By removing the AND and the duplicate value/variable to get:

A op1 B op2 C

But the language used by the MACRO PROCESSOR does NOT support that abbreviated syntax.

 

If you have a question about how to expand an abbreviated expression you can use it in a WHERE statement and SAS will echo to restructured syntax in the log.

1    data want;
2      set sashelp.class;
3      where age < height < weight ;
4    run;

NOTE: There were 18 observations read from the data set SASHELP.CLASS.
      WHERE (age<height) and (height<weight);
NOTE: The data set WORK.WANT has 18 observations and 5 variables.
NOTE: DATA statement used (Total process time):
      real time           0.07 seconds
      cpu time            0.01 seconds
ballardw
Super User

@Bill3 wrote:

for example: Step1: %let tab=3; %macro test(); %if 1<&tab.<4 %then %do; %put it worked; %end; %mend test; %test; Step2: when i modified "%let tab =4; it still prints "it worked".


A couple of tests make me think that the way the SAS Macro processor handles something like 1<3<4 is that it first, left to right, resolves the first comparison: 1<3. Which may return 0 for False or 1 for true. Then uses that result in the <4. So pretty much regardless what the first comparison would be the result is 1 because both 1 and 0 are less than 4.

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 7 replies
  • 1575 views
  • 2 likes
  • 5 in conversation