3

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.

2 Answers 2

4

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
*/
Sign up to request clarification or add additional context in comments.

1 Comment

Yes I use fcmp it is very good; but I was looking for a way to do it with only macros. Thanks
2

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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.