Hi,
Came across something today that challenged my understanding of how I thought macro code worked vs the code the macro generates.
I've always though macro invocation completed prior to any of the code it generated getting run. Apparently that isn't the case.
Here's the log from a simple test using sashelp.baseball. Note that the 1st observation in the baseball dataset does have Cleveland as a value, so the team macro variable would be created at the end of the data step.
I was under the impression though that the entire macro runs prior to any code it generates is run. If that were the case, the team macro variable below would not exist prior to the %if checks after the macro was run. What I'm seeing is the macro processor is feeding statements to the input stream of the SAS processor and running the code at each step boundary. Am I reading this correctly?
Thanks!
--Ben
4715 %macro checkteam;
4716 data _null_;
4717 set sashelp.baseball;
4718 if team='Cleveland' then do;
4719 call symputx('team',team);
4720 stop;
4721 end;
4722 run;
4723
4724 %put &=team;
4725 %if &team=Oakland %then %put It was Oakdland;
4726 %if &team=Cleveland %then %put It was Cleveland;
4727 %mend;
4728 options mlogic symbolgen mprint;
4729
4730 %put &=team;
WARNING: Apparent symbolic reference TEAM not resolved.
team
4731 %checkteam;
MLOGIC(CHECKTEAM): Beginning execution.
MPRINT(CHECKTEAM): data _null_;
MPRINT(CHECKTEAM): set sashelp.baseball;
MPRINT(CHECKTEAM): if team='Cleveland' then do;
MPRINT(CHECKTEAM): call symputx('team',team);
MPRINT(CHECKTEAM): stop;
MPRINT(CHECKTEAM): end;
MPRINT(CHECKTEAM): run;
NOTE: There were 1 observations read from the data set SASHELP.BASEBALL.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
MLOGIC(CHECKTEAM): %PUT &=team
SYMBOLGEN: Macro variable TEAM resolves to Cleveland
TEAM=Cleveland
SYMBOLGEN: Macro variable TEAM resolves to Cleveland
MLOGIC(CHECKTEAM): %IF condition &team=Oakland is FALSE
SYMBOLGEN: Macro variable TEAM resolves to Cleveland
MLOGIC(CHECKTEAM): %IF condition &team=Cleveland is TRUE
MLOGIC(CHECKTEAM): %PUT It was Cleveland
It was Cleveland
MLOGIC(CHECKTEAM): Ending execution.
As the macro emits SAS code the code is compiled and run the same way it would have run if that same code was hard coded into the source file.
So when the macro finishes emitting a DATA step the data step runs. When that step is finished the macro processor can continue emitting new code.
Where you might experience what you thought would happen is if you submit a macro call with CALL EXECUTE(). If you do not protect the macro call with %NRSTR() then the macro execute while CALL EXECUTE is storing the code onto the stack to run after the current data step runs. So the data step does not actually have a chance to run (it is waiting for the step that submitted it to finish) so the macro logic executes before the data step runs.
To see this with your macro run these two data steps.
data _null_;
call execute('%checkteam;');
run;
data _null_;
call execute('%nrstr(%checkteam);');
run;
As the macro emits SAS code the code is compiled and run the same way it would have run if that same code was hard coded into the source file.
So when the macro finishes emitting a DATA step the data step runs. When that step is finished the macro processor can continue emitting new code.
Where you might experience what you thought would happen is if you submit a macro call with CALL EXECUTE(). If you do not protect the macro call with %NRSTR() then the macro execute while CALL EXECUTE is storing the code onto the stack to run after the current data step runs. So the data step does not actually have a chance to run (it is waiting for the step that submitted it to finish) so the macro logic executes before the data step runs.
To see this with your macro run these two data steps.
data _null_;
call execute('%checkteam;');
run;
data _null_;
call execute('%nrstr(%checkteam);');
run;
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
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.