BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
CalleC
Calcite | Level 5

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

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. 

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.

View solution in original post

4 REPLIES 4
Tom
Super User Tom
Super User

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.

Quentin
Super User

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. 

The Boston Area SAS Users Group (BASUG) is hosting our in person SAS Blowout on Oct 18!
This full-day event in Cambridge, Mass features four presenters from SAS, presenting on a range of SAS 9 programming topics. Pre-registration by Oct 15 is required.
Full details and registration info at https://www.basug.org/events.
CalleC
Calcite | Level 5
Brilliant, many thanks all for your prompt help to improve my understanding of local macro variables 🙂

SAS Innovate 2025: Call for Content

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!

Submit your idea!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 460 views
  • 8 likes
  • 4 in conversation