Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- Home
- /
- SAS Programming
- /
- SAS Procedures
- /
- use of %eval

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

10-31-2012 02:29 PM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to varunnakra

10-31-2012 02:42 PM

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

All Replies

Solution

10-31-2012
02:42 PM

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to varunnakra

10-31-2012 02:42 PM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to varunnakra

10-31-2012 04:32 PM

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.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to varunnakra

10-31-2012 04:37 PM

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;

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to Reeza

11-01-2012 12:59 AM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to varunnakra

10-31-2012 10:46 PM

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.

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

11-01-2012 01:03 AM

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

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to varunnakra

11-01-2012 07:50 AM

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.