Sparc_Spread explains how to "call by reference" in the SAS macro language, which may solve your problem.
In this particular case though, it's not necessarily crucial to use call by reference, and I'd argue it's not idiomatic to SAS macro language to use it (though certainly nothing wrong with it - it just looks a bit odd, and is a bit harder since it's not really a native concept, though certainly intentionally supported to be used that way if desired). There are two ways to get around this that both are very easy to use.
First of all, let's say you know the variable name you want to increment, and the starting value is the only interesting thing. Thanks to how SAS macro language handles scoping, with something not exactly lexical scoping and not exactly functional, it automatically will use the variable that already exists in the most local scope, when it does already exist (with some minor caveats, such as macros using DOSUBL).
So this works as expected:
%macro macro2(counter=);
%do variable1 =&counter. %to 200;
%if %sysfunc(mod(&variable1.,50))=0 %then %put &=variable1;
%end;
%mend macro2;
%macro macro1();
%let variable1= 0;
%macro2(counter=&variable1.);
%put &=variable1;
%mend macro1;
%macro1;
(Of course, that is if you expect &variable1 to have the value of 201 - because %do
loops, like do
loops, always get incremented one higher than their ending value. I assume your real procedure works differently.)
That's because the &variable1.
referred to in %macro2
automatically is the one present in the most local scope - which in this case is the scope of %macro1
.
Alternatively, if you're using this %macro2
for the purpose of incrementing a counter, I would use a function-style macro
method.
A function-style macro by definition is one that returns only a single value - and by returns
I mean has a single value at the end of the macro's code that is presented in plain text (since a macro is, after all, only intended to create text that will then be parsed by the normal SAS language parser).
This can then be used on the right side of an equal sign in an assignment statement. The key is that it uses only macro language elements - %do
loops and such - and no data step, proc, etc., language that would prevent it from being on the right side of an equal sign in an assignment statement (ie, x=%macrostuff();
cannot be x=proc sql(select...)
).
So the following accomplishes the goal: increment a counter some amount, return the value (201, in this case, just like before), and then that can be assigned to a macro variable.
%macro macro2(counter=);
%do internal_counter =&counter. %to 200;
%if %sysfunc(mod(&internal_counter.,50))=0 %then %put &=internal_counter.;
%end;
&internal_counter.
%mend macro2;
%macro macro1();
%let variable1= %macro2(counter=0);
%put &=variable1;
%mend macro1;
%macro1;
I would suggest that this is the most idiomatic way to accomplish this, and the most simple: you pass the value you want as input, function operates on it, returns value, which you then assign to a variable in your macro however you want.