BookmarkSubscribeRSS Feed
monicazhou2013
Calcite | Level 5
%let mv = shoes;
%macro product (mv = bicycles);
%let mv = clothes;
%mend;
%product(mv = tents)
%put mv is &mv;

How is the answer " mv is shoes" processed? I see somebody says when the local macros finished execution, they disappear, so the answer will be the global macro "shoes".  If this is true, why the next problem does not choose the global macro ("cat") as the answer? 

 Another problem: Why the answer is "a is dog" rather than cat (I think "cat" is global macro)?

%let a=cat;
%macro animal;
%let a=dog;
%mend;
%animal
%put a is &a;
14 REPLIES 14
WarrenKuhfeld
Rhodochrosite | Level 12

A macro parameter [specified in %macro ()] is not treated the same way as a %let statement inside the macro.  The %let statement uses the already existing macro name in its already defined scope.  Google "scope of sas macro variables" for more info.

Astounding
PROC Star

Agreeing with @WarrenKuhfeld and adding some explanation ...

 

%LET does not automatically create a new macro variable.  It first looks to see if it can find an existing macro variable with the right name.  If the search is successful, that's the variable %LET uses.

 

So the top program looks first in the local symbol table, finds &MV there (with a value of bicycles), and changes its value to clothes.  The macro ends, the local symbol table disappears, and the %PUT statement uses the only &MV it can find, the one in the global symbol table.

 

The bottom program forces %LET to look for an existing macro variable (&A).  It finds nothing in the local symbol table, so it searches the global symbol table.  Finding &A (with a value of cat), it changes the value to dog.  There is never a local macro variable named &A.  Both %LET and %PUT use the global macro variable &A.

GinaRepole
SAS Employee

When working with macro variables and scoping, I like to visualize it like each variable within the macro program is a piece of paper that you're adding to a stack. We start off and put the mv (shoes) piece of paper onto the stack, which is just the one paper right now. We can see that paper and take it away or update it whenever we want. But when we move into the %product macro, we have to add a new piece of paper. This is the positional parameter mv. This is NOT the same mv from before; this is a local macro variable. It needs a new piece of paper. So now we have a piece of paper called mv (tents). After adding that paper, we see it's time to update mv to clothes. But it's hard to get to the original macro variable because that paper is UNDER the new piece of paper! Since we can't get to that variable without moving our papers around, we instead update our top sheet (the local mv) When we see %mend, that means all the local variables need to be removed. We take off and throw away the mv (clothes) paper. Now the only variable left is the original macro variable mv (shoes). That's what prints when we run the program.

 

Why is this different than the dog and cat example?

 

We start off easy again: a single piece of paper called a (cat). We go inside the macro %animal and we IMMEDIATELY see a reassignment to that macro variable a. Since it's already on the top of the stack, we're able to make changes to that paper without moving anything else around or creating a new, local version of a. We scratch out a (cat) and write a (dog). The macro is able to complete with only a single piece of paper running around, so the values change as you would expect, given their names.

 

Hope this helps if you're struggling with the visuals!

monicazhou2013
Calcite | Level 5

Thank you very much for your picturesque explanation! I think it still needs me to put some effort to understand completely! But your answer really helps a lot! Thank you a lot!

monicazhou2013
Calcite | Level 5

Thank you very much for your time to answer my question, now I totally got it after several days thinking about it.

Tom
Super User Tom
Super User

Using the command

%put _user_;

Can really help make the difference clearer.

So here is the result if we run the first macro:

1    %let mv = shoes;
2    %macro product (mv = bicycles);
3    %put _user_;
4    %let mv = clothes;
5    %put _user_;
6    %mend;
7    %product(mv = tents)
PRODUCT MV tents
GLOBAL MV shoes
PRODUCT MV clothes
GLOBAL MV shoes
8    %put mv is &mv;
mv is shoes

So you can see that when %PRODUCT starts there are two macro variables name MV. One is GLOBAL symbol table and one in the PRODUCT symbol table.  It is this most local version that is updated by the %LET statement.

Now if you run the second example you can see that there never is a local macro variable named A.

9    %let a=cat;
10   %macro animal;
11   %put _user_;
12   %let a=dog;
13   %put _user_;
14   %mend;
15   %animal
GLOBAL A cat
GLOBAL MV shoes
GLOBAL A dog
GLOBAL MV shoes
16   %put a is &a;
a is dog

 

monicazhou2013
Calcite | Level 5

Thank you very much for answering my question! Your answer is really helpful although I already use this method (options symbolgen mlogic) to comprehend this program.

Reeza
Super User

@monicazhou2013 please take the time to mark a solution as the answer.  

LL5
Pyrite | Level 9 LL5
Pyrite | Level 9
Saw this post today and I wonder why dog is a global variable in the second program. It’s little confusing to me that variable created inside macro is a global variable. Can anyone give me some advices? Thanks.
Astounding
PROC Star

In the second program, &A is created before the macro begins.

 

When the macro executes, it finds there is an existing &A (in the global table) and therefore uses the existing &A, changing its value from cat to dog.

Tom
Super User Tom
Super User

@LL5 wrote:
Saw this post today and I wonder why dog is a global variable in the second program. It’s little confusing to me that variable created inside macro is a global variable. Can anyone give me some advices? Thanks.

There is no macro variable named DOG in any of the programs.

 

In the second program the macro variable is named A. It is created outside of any macro environment and so it is created in the global symbol table. When the macro runs it sets the value of A to dog. It does not create a macro variable in the local symbol table since there was already a macro variable named A that the %let statement could use.

LL5
Pyrite | Level 9 LL5
Pyrite | Level 9
If I’m following this logic, that means &A is created in the global symbol table before the macro begins, which is cat. But then when macro executes, it finds another global variable for &A which is dog, so macro processor replace cat by dog?
Tom
Super User Tom
Super User

@LL5 wrote:
If I’m following this logic, that means &A is created in the global symbol table before the macro begins, which is cat. But then when macro executes, it finds another global variable for &A which is dog, so macro processor replace cat by dog?

"&A" is not created anywhere.  The syntax &A is a reference to the value of a macro variable named A. 

The macro variable A was created in the global symbol table by the %LET statement that assigned it a value of cat. 

When the macro runs the %LET statement in the macro assigns a new value of dog to the macro variable named A.  Because nothing ever created a local macro variable named A the value is assigned to the existing macro variable A, the one in the global symbol table.

LL5
Pyrite | Level 9 LL5
Pyrite | Level 9
Thanks Tom. I might understand the logic. So I did a testing as below and made A inside the macro as a local variable, then &A becomes cat now - see log below. So following the logic, since in the original program, nothing was created in the local symbol table, so the value of dog was assigned to the existing macro variable A?

%LET A=CAT;
%MACRO ANIMAL;
%LOCAL A;
%LET A=DOG;
%MEND;
%ANIMAL
%PUT A IS &A

;
NOTE: Writing TAGSETS.SASREPORT13(EGSR) Body file: EGSR
21
22 GOPTIONS ACCESSIBLE;
23 %LET A=CAT;
24 %MACRO ANIMAL;
25 %LOCAL A;
26 %LET A=DOG;
27 %MEND;
28 %ANIMAL
MLOGIC(ANIMAL): Beginning execution.
MLOGIC(ANIMAL): %LOCAL A
MLOGIC(ANIMAL): %LET (variable name is A)
MLOGIC(ANIMAL): Ending execution.
29 %PUT A IS &A
SYMBOLGEN: Macro variable A resolves to CAT
30
31 GOPTIONS NOACCESSIBLE;
A IS CAT GOPTIONS NOACCESSIBLE

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

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
  • 14 replies
  • 4376 views
  • 3 likes
  • 7 in conversation