I found this very helpful SO page while trying to resolve an issue related to macro variable scope. why doesn't %let create a local macro variable?
So to summarize, writing %let x = [];
or %do x = [] %to [];
in a macro will:
- create a local-scope macro variable x if there is no "x" already in the global symbol table, or
- update the global-scope macro variable "x" if an "x" is in the global symbol table
This strikes me as very non-intuitive. I would be willing to bet there are tons of bugs out in the SAS wilderness due to this design choice. I rarely see %local statements in macros, even above loop statements using common variable names like "i" or "counter." For example, I just pulled up the first paper with the word "macro" in the title from this list of SUGI and SAS Global Forum papers http://www.lexjansen.com/cgi-bin/xsl_transform.php?x=sgf2015&c=sugi
And indeed, I found this code in the first SAS conference paper I opened:
%macro flag;
data CLAIMS;
set CLAIMS;
%do j= 1 %to 3;
if icd9px&j in (&codelist)
then _prostate=1;
%end;
run;
%mend;
%flag;
http://support.sas.com/resources/papers/proceedings15/1340-2015.pdf
Woe unto anyone who calls %flag and also has their own &j variable. They could easily end up with no log errors but bogus results because their &j is 4 everywhere after they call %flag, which will be (from experience) a bug that is no fun to track down. Or worse, they may never recognize their results are bogus.
So my question is, why was the decision made not to have all macro variables be local scope by default? Are there good reasons why SAS macro variable scope works the way it does?