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

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

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
  • 1335 views
  • 2 likes
  • 5 in conversation