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!
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
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
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.
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;
yes, i am sorry to have missed on the %'s and the &'s.. I was writing this code here feeling a little dizzy..
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.
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..
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.
Don't miss out on SAS Innovate - Register now for the FREE Livestream!
Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.
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.