Help using Base SAS procedures

use of %eval

Accepted Solution Solved
Reply
Contributor
Posts: 29
Accepted Solution

use of %eval

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!


Accepted Solutions
Solution
‎10-31-2012 02:42 PM
Frequent Contributor
Posts: 129

Re: use of %eval

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


All Replies
Solution
‎10-31-2012 02:42 PM
Frequent Contributor
Posts: 129

Re: use of %eval

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

Super User
Posts: 5,081

Re: use of %eval

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.

Super User
Posts: 17,784

Re: use of %eval

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;

Contributor
Posts: 29

Re: use of %eval

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

Super User
Super User
Posts: 6,499

Re: use of %eval

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.

Contributor
Posts: 29

Re: use of %eval

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..

Super User
Super User
Posts: 6,499

Re: use of %eval

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.

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

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