This is related to this question: SAS macro variable change.
The code below explains the problem:
%macro test (arg=);
options mlogic mprint symbolgen;
array arraytwo [%EVAL(&arg+1)] _temporary_;
sum=0;
%do i = 1 %to %EVAL(&arg+1);
sum=sum+&i;
arraytwo[&i]=sum;
%end;
return=arraytwo[&arg+1];
%mend test;
/* This is ok */
data dat1;
%test(arg=9);
run;
data dat2;
input M;
cards;
5
6
7
;
run;
/* This give an error= A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: M+1 */
data dat3;
set dat2;
%test(arg=M);
run;
So the question is why does it bug in the last test? Thanks.
If you happen to be using SAS 9.2 or later you might want to look at proc fcmp to create a function to do this.
If you write it as a function instead of a macro, you can pass in data set variables that would resolve to numeric values - or pass numeric values directly. For example, try this code:
proc fcmp outlib=work.funcs.simple;
function sumloop(iter);
x=1;
do i=1 to iter+1;
x+i;
end;
return(x);
endsub;
run;
/* point to the location the function was saved in */
option cmplib=work.funcs;
data _null_;
input M;
y=sumloop(M); /* data set variable */
z=sumloop(9); /* static numeric value */
put M= @7 y= @14 z= @20 ;
cards;
1
2
3
4
5
6
7
8
9
;
run;
/* My log looks like this:
14 data _null_;
15 input M;
16 y=sumloop(M); /* data set variable */
17 z=sumloop(9); /* static numeric value */
18 put M= @7 y= @14 z= @20 ;
19 cards;
M=1 y=3 z=55
M=2 y=6 z=55
M=3 y=10 z=55
M=4 y=15 z=55
M=5 y=21 z=55
M=6 y=28 z=55
M=7 y=36 z=55
M=8 y=45 z=55
M=9 y=55 z=55
*/
I have to say I'm not entirely sure what you're trying to do; but does this give you the results you're looking for? The problem with your code above is the way you are trying to combine dataset variables and macro variables-- it isn't as easy to do as one might hope...
%macro test (argList=, totNumObs=);
%local arg;
%local j;
%local i;
%do j = 1 %to &totNumObs;
%let arg = %scan(&argList, &j);
array array&j [%EVAL(&arg+1)] _temporary_;
sum = 0;
%do i = 1 %to %EVAL(&arg+1);
sum = sum+&i;
array&j[&i] = sum;
%end;
return = array&j[&arg+1];
output;
%end;
%mend test;
data dat2;
input M;
cards;
5
6
7
;
run;
proc sql noprint;
select
count (*) into :numObs
from dat2 ;
select
M into :listofMs separated by ' '
from dat2
order by M;
quit;
options mlogic mprint symbolgen;
data dat3;
%test(argList= &listofMs, totNumObs= &numObs);
run;
proc print data= dat3;
run;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With