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

Please look at the code below -

%macro testeval;

%let cnt = 0;

%do until(&cnt =5);

%let cnt = &cnt + 1;

%put cnt;

%end;

%mend;

has the following output:

0 + 1

0 + 1 + 1

0 + 1 + 1 + 1

0 + 1 + 1 + 1 + 1

0 + 1 + 1 + 1 + 1 + 1

The loop goes till 5 iterations which means the integral sum is being calculated and the value of cnt is 5 as understood by the SAS system, however, as an output the values of cnt are not 1,2,3,4,5.

If we use %eval(&cnt + 1), we can have those values of cnt but still, the SAS system executes the loop 5 times..Then why doesn't it output those values..or does this mean that we can perform logical and arithmetic operations on macro variables (integral values) without the use of %eval but can get their true values?

Please enlighten!

1 ACCEPTED SOLUTION

Accepted Solutions
LarryWorley
Fluorite | Level 6

varunnakra,

Perhaps this will help.

When a macro variable is logically compared to a constant integer, such as your until clause (&cnt =5), the macro compiller does an explicit %eval for the comparison.  So 0 +1 is not equal to 5 but 0 + 1 +1 +1 +1 +1 is equal to 5.  This does not change the internal value of cnt which is always something like 0, 0 +1, 0 +1 +1, etc.

try adding %eval in your let statement -- %let cnt = %eval(&cnt + 1) ;  That will explicitly do the integer arithmetic.  In your original case, you are just appending the string ' + 1' to the previous string value of cnt.

Larry

View solution in original post

7 REPLIES 7
LarryWorley
Fluorite | Level 6

varunnakra,

Perhaps this will help.

When a macro variable is logically compared to a constant integer, such as your until clause (&cnt =5), the macro compiller does an explicit %eval for the comparison.  So 0 +1 is not equal to 5 but 0 + 1 +1 +1 +1 +1 is equal to 5.  This does not change the internal value of cnt which is always something like 0, 0 +1, 0 +1 +1, etc.

try adding %eval in your let statement -- %let cnt = %eval(&cnt + 1) ;  That will explicitly do the integer arithmetic.  In your original case, you are just appending the string ' + 1' to the previous string value of cnt.

Larry

Astounding
PROC Star

There are some cases where you can perform arithmetic on macro variables without specifying %eval.  Macro language does it for you.  For example, if a mathematical operator appears in a %IF condition, macro language attempts to perform the math.  So this group of statements finds a Match:

%let a = 5;

%let b = 3 + 2;

%put &a &b;

%if &a = &b %then %put Match;


There are other places where %EVAL is assumed to be needed, such as here:

%do i=1 %to &b;

This automatic invocation of %EVAL is not always your friend.  The first statement below is perfectly legal, but the second always generates an error message:

%let rank = A-1;

%if &rank = A-1 %then %do;

The %IF statement sees subtraction, and attempts to perform math on A-1.  There are ways around this, but the answer to your original question is that macro language has situations where it decides to apply the %EVAL function for you.

Reeza
Super User

You have both variables cnt and &cnt, did you mean to do that. I find that can confuse me fast.

ie %put cnt should be %put &cnt

And you need a % before the until.

The following works fine for me.

%macro testeval;

%let cnt = 0;

%do %until (&cnt=5);

    %let cnt = %eval(&cnt + 1);

    %put &cnt;

%end;

%mend;

%testeval;

varunnakra
Fluorite | Level 6

yes, i am sorry to have missed on the %'s and the &'s.. I was writing this code here feeling a little dizzy.. 

Tom
Super User Tom
Super User

When you have a test in macro code then SAS does an implied %EVAL().  This is true for %IF and %DO conditions.

So it is as if you coded :

%do %until ( %eval(&cnt = 5) ) ;

That is why the string "0 + 1 + 1 + 1 + 1 + 1" that you are generating into your macro variable CNT caused the %DO loop to stop.

varunnakra
Fluorite | Level 6

Conclusively, one must use %eval in logical or arithmetic operations just to be sure that there is not an error when SAS doesnt perform an automatic conversion..

Tom
Super User Tom
Super User

I would flip that around.  I wouldn't worry about the automatic insertion of %EVAL() but instead remember to think of macro code as generating strings. In particular in your example the problem was in your %LET statement and not in the %UNTIL() clause.

Also remember that if you want to evaluate floating point arithmetic in macro world you will need to use the %SYSEVALF() function.  %EVAL() only does integer arithmetic.

In general macro code is not a good place to perform mathematical operations, in general you should arrange your code so that such activity is happening in PROC's and DATA steps.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 7 replies
  • 2335 views
  • 8 likes
  • 5 in conversation