I have encountered the following behavior in SAS EG (Version 7.11 64-bit) that I am struggling to understand.
When I run the code below, I see the value of tempvar in work.temp2 get set to '20'
Then I edit the code line
call execute('%getVarNumber(vn=20);');
to
call execute('%getVarNumber(vn=30);');
but when I run the code the value of tempvar in work.temp2 remains '20' on the first run but updates to '30' the second time I run it.
CODE:
DATA work.temp; INPUT A; DATALINES; 1 4 ; %macro getVarNumber (vn=); %global varName2; %let varName2=&vn; %put &varName2; %mend getVarNumber; data work.temp2; set WORK.temp; putlog VARNUM; call execute('%getVarNumber(vn=20);'); temp=&varName2; putlog temp; run;
Some languages execute each statement in order, as the statement is submitted. SAS does not. Consider the end of your program:
data work.temp2; set WORK.temp; putlog VARNUM; call execute('%getVarNumber(vn=20);'); temp=&varName2; putlog temp; run;
SAS sees the DATA statement and figures out what it means. But it doesn't execute anything yet.
It sees the SET statement, and same thing ... figure out what it means but don't execute anything yet.
Same for all the statements in the DATA step ... SAS figures out what they mean, but doesn't execute anything yet. As part of that process, this statement must use the previously assigned value for &varName2: temp=&varName2;
When SAS finally encounters the RUN statement, it knows that it has all the statements related to the DATA step and actually runs them. But the value being assigned to TEMP depends on the value of &varName2 before the DATA step began to execute. That value was in effect when SAS "figured out" what temp=&varName2; actually meant.
What are you actually attempting to do?
CALL EXECUTE creates code that actually executes after the data step that makes the calls ends.
And when I run this code I get this error (not unexpected actually the first time)
781 data work.temp2; 782 set WORK.temp; 783 putlog VARNUM; 784 call execute('%getVarNumber(vn=20);'); 785 temp=&varName2; - 22 WARNING: Apparent symbolic reference VARNAME2 not resolved. ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string, a numeric constant, a datetime constant, a missing value, INPUT, PUT. 786 putlog temp; 787 run;
Macro variables in a data step such as your &varname2 are resolved as the data step compiles, way before any actual data is read.
So you are getting the macro value from the LAST time you ran that set.
Also in general because of that timing you can't easily reference the value of a macro variable in the data step it is created.
CALL EXECUTE works after the data step is done.
If you want to resolve a macro variable within the data step, use SYMGET function.
@mk123451243 wrote:
I have encountered the following behavior in SAS EG (Version 7.11 64-bit) that I am struggling to understand.
When I run the code below, I see the value of tempvar in work.temp2 get set to '20'
Then I edit the code line
call execute('%getVarNumber(vn=20);');to
call execute('%getVarNumber(vn=30);');but when I run the code the value of tempvar in work.temp2 remains '20' on the first run but updates to '30' the second time I run it.
CODE:
DATA work.temp; INPUT A; DATALINES; 1 4 ; %macro getVarNumber (vn=); %global varName2; %let varName2=&vn; %put &varName2; %mend getVarNumber; data work.temp2; set WORK.temp; putlog VARNUM; call execute('%getVarNumber(vn=20);'); temp=&varName2; putlog temp; run;
Some languages execute each statement in order, as the statement is submitted. SAS does not. Consider the end of your program:
data work.temp2; set WORK.temp; putlog VARNUM; call execute('%getVarNumber(vn=20);'); temp=&varName2; putlog temp; run;
SAS sees the DATA statement and figures out what it means. But it doesn't execute anything yet.
It sees the SET statement, and same thing ... figure out what it means but don't execute anything yet.
Same for all the statements in the DATA step ... SAS figures out what they mean, but doesn't execute anything yet. As part of that process, this statement must use the previously assigned value for &varName2: temp=&varName2;
When SAS finally encounters the RUN statement, it knows that it has all the statements related to the DATA step and actually runs them. But the value being assigned to TEMP depends on the value of &varName2 before the DATA step began to execute. That value was in effect when SAS "figured out" what temp=&varName2; actually meant.
The macro processor processes the code and resolves macro variable references and then passes the result to SAS to execute. CALL EXECUTE() pushes code onto a stack to execute after the current data step finishes. Your first attempt should have given a warning that VARNAME2 was not defined.
Basically you ran this code:
%let varname2=30;
data work.temp2;
set WORK.temp;
putlog VARNUM;
call execute('%getVarNumber(vn=20);');
temp=30;
putlog temp;
run;
%let varname2=20;
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.
Ready to level-up your skills? Choose your own adventure.