BookmarkSubscribeRSS Feed
Black
Calcite | Level 5
I don't know why there are three "&& resolves to &." in the middle of log information.

program as follows:
%let out1=a;
%let previtem=1;
%let y=y1;
%let y1=z;
%put &&out&previtem&&y; /*submit first*/

%put &&out&previtem&&&y;/*submit second*/

First:
the log show:
29 %put &&out&previtem&&y;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable PREVITEM resolves to 1
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable OUT1 resolves to a
SYMBOLGEN: Macro variable Y resolves to y1
ay1

Second:
the log file show:
30 %put &&out&previtem&&&y
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable PREVITEM resolves to 1
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable Y resolves to y1


Can anyone tell me the reason? Thank you very much. Message was edited by: Black
11 REPLIES 11
Cynthia_sas
SAS Super FREQ
Hi:
There are 2 rules of macro variable resolution that you have to know about in order to understand what is happening (aside from the LOG messages): the forward scan rule and the rescan rule.

The forward scan rule says that the macro processor should march from left to right through the macro variable and resolve references based on what it finds...and that every 2 consecutive ampersands resolve to 1 ampersand. After the macro processor marches forward and has resolved what it can, then the rescan rule kicks into effect. The rescan rule says that the macro processor has to go back to the beginning of the string and start marching and resolving again until all the macro references are either resolved or error messages have been issued.

I can show how these 2 strings will be resolved differently. I don't know why it appears that there are some extra && resolves to & in the log. But the messages in the log are not as important as whether the results from the use of &&& are what you want.

When I run your code, this is what I get in the log:
[pre]
143 options symbolgen;
144 %let out1=a;
145 %let previtem=1;
146 %let y=y1;
147 %let y1=z;
148
149 %put &&out&previtem&&y;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable PREVITEM resolves to 1
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable OUT1 resolves to a
SYMBOLGEN: Macro variable Y resolves to y1
ay1 <---------------------final resolution with &&y

150
151
152 %put &&out&previtem&&&y;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable PREVITEM resolves to 1
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable Y resolves to y1
SYMBOLGEN: Macro variable OUT1 resolves to a
SYMBOLGEN: Macro variable Y1 resolves to z
az <---------------------final resolution with &&&y


[/pre]

In the first instance of %put &&out&previtem&&y; , let's look at how that breaks down, ignoring the log messages:
[pre]
start with: &&out&previtem&&y
break up string: &&out &previtem &&y
after first scan: & out 1 &y
this is left: &out1&y
after second scan: a y1
all resolved to: ay1
[/pre]

Now, let's compare that to the secong string of &&out&previtem&&&y and see how the 3 &&& make a difference in resolution:
[pre]
start with: &&out&previtem&&&y
break up string: &&out &previtem &&&y
after first scan: & out 1 & &y
this is left: &out1&&y
after second scan: a & y1
this is left: a&y1
after third scan: a &y1
all resolved to: az
[/pre]

It does seem like symbolgen gives you an extra && resolves to & in the log from the first %PUT. But, worrying about whether the log got confused or whether the macro processor made an extra pass is less important than whether you got what you wanted out of the two different references.

cynthia
Black
Calcite | Level 5
Hi, Cynthia:

I don't think the second code scan for three times. my understanding is:
start with: &&out&previtem&&&y
break up string: &&out &previtem &&&y
after first scan: & out 1 & y1
this is left: &out1 &y1
after second scan: a z

all resolved to: az
Cynthia_sas
SAS Super FREQ
HI:
I think it really comes down to how you understand it. I think of the scan of a string (or line of code) at being more of this process:
scan-find macro trigger-resolve -- keep going forward thru the string -- scan-find macro trigger-resolve -- keep going forward thru the string.

So, in my way of thinking about it,
& out 1 & y 1 is TWO scan/resolves
&out1 is one scan/resolve and &y1 is a second scan/resolve

where it all started:
&&out&previtem&&&y is
&& (one scan/resolve to &)
out (just a scan -- no triggers found)
&previtem (one scan/resolve to 1)
&& (one scan/resolve to &)
&y (one scan/resolve to y1)

Therefore, a single line of code could have more than one scan/resolve sequence. That's how I think of the forward scan rule -- always marching forward thru the string, scanning and resolving. The rescan rule says that the macro processor/parser/tokenizer has to "rescan" the preliminary result of the attempt to resolve to see if there are other macro tokens left unresolved.

Everybody has to come to their own way to work through indirect reference of macro variables and how macro variables and macro invocations operate within the whole compile/execute mode of running SAS code. I think of the macro processor as a big, smart, typewriter whose only purpose is to generate code for me. The resolved code is what gets sent to the compiler. The compiler NEVER sees the macro variable or macro invocation references.

Whatever works for you, works for you. I've come to my understanding of how it works after 20+ years of macro programming. I still consider my understanding to be imperfect and in a state of constant refinement.

cynthia
Black
Calcite | Level 5
Form your sharing of understanding about macro programming, i can see you are a very excellent programmer.
Thank you very much, Cynthia. Message was edited by: Black
Zhanxiong
Obsidian | Level 7

Hi, Cynthia,

 

Thanks for your posting, I learned much from it. However, I am unable to follow this step:

 

"break up the string: &&out &previtem &&y".

 

Is there any particular reason to break the string in this way? I carefully read your explanation about the forward scan rule and the rescan rule and I think neither the forward scan rule and the rescan rule implies it. For example, let's consider the following code:

 

%let d = one;

%put &&&&d;

 

For this case, how should I perform the step: break up the string? There seem no clear boundaries as the first example we can break the string up. 

 

The below is my own understanding, please correct me if it is wrong: It seems that at one time, from left to right, SAS tries to resolve all the macro variables indicated by & simultaneously, so for the first example &&out&previtem&&y, in the first attempt (scan), SAS resolves "&&", "&previtem", and "&&" to "&", "1" and "&" respectively, while keeping "out" and "y" unchanged, producing

 

"&out1&y",

 

then starts the second scan. At this time, there are two and only two macro variables &out1 and &y, and will be resolved to "ay1".  In 

"ay1", no macro variable is detected, so the resolve procedure ends.

 

In my example "&&&&d", in the first scan, SAS resolves "&&" and "&&" to "&" and "&", leaving "&&d" for the second scan, which resolves to "&d", and finally "one".

 

Thanks again for your time. 

 

Black
Calcite | Level 5
Thank you for your explanation of the basic rules about macro variable resolution, and illustrating how the results are resolved.

I will concentrate more energy on the result that i want, and not the log information.
Cynthia_sas
SAS Super FREQ
Hi:
I didn't mean to imply that you should ignore ALL the symbolgen messages in the log...if you focus on THESE, you will see that they essentially reveal the macro variables which were finally resolved with each scan:
[pre]
394 %put &&out&previtem&&y;
...
SYMBOLGEN: Macro variable PREVITEM resolves to 1
...
SYMBOLGEN: Macro variable OUT1 resolves to a
SYMBOLGEN: Macro variable Y resolves to y1
ay1


397 %put &&out&previtem&&&y;
...
SYMBOLGEN: Macro variable PREVITEM resolves to 1
...
SYMBOLGEN: Macro variable Y resolves to y1
SYMBOLGEN: Macro variable OUT1 resolves to a
SYMBOLGEN: Macro variable Y1 resolves to z
az
[/pre]

cynthia
Black
Calcite | Level 5
I see. Thank you, dear friend.
deleted_user
Not applicable
Hi,

I have a question regarding this. Following is an excerpt of Cynthia's post above where she explains how the macro variables are resolved in case of 3 ampersands.

start with: &&out&previtem&&&y
break up string: &&out &previtem &&&y
after first scan: & out 1 & &y --------------------understood
this is left: &out1&&y
after second scan: a & y1 --------------------unable to follow
this is left: a&y1
after third scan: a &y1 --------------------understood
all resolved to: az


What I did not understand is when we are left with &&y, why does the macro processor reslove it to &(&y) that is &y1 instead to (&&)y and get &y as in step 1 in case of &&out?
Cynthia_sas
SAS Super FREQ
Hi:
This -is- why there is a macro processor and we're all happy that it's not me.

[pre]
start with: &&out&previtem&&&y
break up string: &&out &previtem &&&y
after first scan: & out 1 & &y ----- marching forward from the 2 ampersands, &y resolves to y1
this is left: &out1 &y1 ----- now &out1 resolves to a and marching forward, &y1 is yet to be resolved
after second resolve: a &y1 -- still marching forward
this is left: a&y1
after third resolve: a &y1 -- still marching forward
all resolved to: az
[/pre]

The foreward scan rule says that the macro processor marches forward and does not "go back" until it's made one complete pass thru the string. So when 2 && resolve to 1 & (as in &&&y1) think of the 2 ampersands as just turning into 1 and then that one is waiting for the RESCAN to happen. But marching forward thru the string is not over yet. so there's still &y to deal with and that resolves to y1. Next time around, the & that was left over gets put with the y1 to become &y1 which becomes z.

I can do two && in my head, 3 or more &&& and I have to start writing it down. Or do a LOT of testing. Which is what I usually do.

cynthia
deleted_user
Not applicable
Understood, thanks a lot Cynthia.

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 11 replies
  • 3922 views
  • 0 likes
  • 4 in conversation