Hi,
As a newbie, I just came across "macro variables". They are said to be local, but then I must misunderstand something. Below is an example that seems to generate a result that gives me the impression that a macro variable (in this case i) is not local within a macro, what do I miss?
%macro macro_B();
%put macro_B ... ;
%do i = 1 %to 5;
%put macro_B - looping [&=i];
%end;
%put macro_B - loop completed [&=i];
%mend;
%macro macro_A();
%put macro_A ... ;
%do i = 1 %to 3;
%put macro_A - looping [&=i];
%macro_B();
%end;
%put macro_A - loop completed [&=i];
%mend;
%macro_A();
Yields the following output
macro_A ...
macro_A - looping [I=1]
macro_B ...
macro_B - looping [I=1]
macro_B - looping [I=2]
macro_B - looping [I=3]
macro_B - looping [I=4]
macro_B - looping [I=5]
macro_B - loop completed [I=6]
macro_A - loop completed [I=7]
Happy for a quick explanation.
//C
That is a lovely test case you wrote up!
The point you are missing is that macro variables defined within a macro are not (necessarily) local by default. Thus if you want a macro variable to be local (which 99.9% of the time is the right design IMHO), you need to use the %LOCAL statement to declare them to be local.
If you add a %LOCAL statement to both macros, they will work as expected:
%macro macro_B();
%local i ;
%put macro_B ... ;
%do i = 1 %to 5;
%put macro_B - looping [&=i];
%end;
%put macro_B - loop completed [&=i];
%mend;
%macro macro_A();
%local i ;
%put macro_A ... ;
%do i = 1 %to 3;
%put macro_A - looping [&=i];
%macro_B()
%end;
%put macro_A - loop completed [&=i];
%mend;
%macro_A()
Without the %local statement, your macro B will not create a local macro variable named i. Instead the %do i=1 %to... statement in the macro B will use the macro variable i that belongs to the macro A. And that will then cause your macro A to stop looping prematurely. These kinds of scope collisions are a common problem if a macro does not declare the macro variables it creates to be %local.
I suspect you do not understand what SAS means by LOCAL.
When you define a macro variable as LOCAL is means that it only exists while it is running. If you call MACRO_B in the middle of running MACRO_A then MACRO_A is still running so the macro variable defined in MACRO_A still exists and can be used by MACRO_B.
When the same macro variable name exists in multiple scopes (GLOBAL, MACRO_A, MACRO_B, etc.) then references will use the most local (inner most) version.
If you define a macro variable as LOCAL that will prevent your macro from modifying some existing macro variable that happened to use the same name. So making a macro variable LOCAL will make your macro play nice with others. But it does not protect its macro variables from being modified by other macros it might call.
That is a lovely test case you wrote up!
The point you are missing is that macro variables defined within a macro are not (necessarily) local by default. Thus if you want a macro variable to be local (which 99.9% of the time is the right design IMHO), you need to use the %LOCAL statement to declare them to be local.
If you add a %LOCAL statement to both macros, they will work as expected:
%macro macro_B();
%local i ;
%put macro_B ... ;
%do i = 1 %to 5;
%put macro_B - looping [&=i];
%end;
%put macro_B - loop completed [&=i];
%mend;
%macro macro_A();
%local i ;
%put macro_A ... ;
%do i = 1 %to 3;
%put macro_A - looping [&=i];
%macro_B()
%end;
%put macro_A - loop completed [&=i];
%mend;
%macro_A()
Without the %local statement, your macro B will not create a local macro variable named i. Instead the %do i=1 %to... statement in the macro B will use the macro variable i that belongs to the macro A. And that will then cause your macro A to stop looping prematurely. These kinds of scope collisions are a common problem if a macro does not declare the macro variables it creates to be %local.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.