[NOTE2013-05-30: This post is permanently suspended. In this post, I only focused on the initialization effect of the %local statement and totally ignored its function to avoid variable collisions as Quentin mentioned in comment box.]
A piece of SAS codes to create a list of all variables within a dataset (a nice programming trick from Art Carpenter, 2004):
%macro getvars(dset) ;
%local varlist ;
%let fid = %sysfunc(open(&dset)) ;
%if &fid %then %do ;
%do i=1 %to %sysfunc(attrn(&fid,nvars)) ;
%let varlist= &varlist %sysfunc(varname(&fid,&i));
%end ;
%let fid = %sysfunc(close(&fid)) ;
%end ;
&varlist
%mend ;%put %getvars(%str(sashelp.iris));
One question would be: why declare macro variable varlist as local explicitly by a %local statement? Since it was defined within the macro %getvar, it just went to the local macro table automatically and the %local statement is not necessary anymore!
Such argument is definitely right. But the %local statement above was not intent to localize a macro variable, actually, it’s used to initiate it. If you just delete it, you will get a warning then an error:
WARNING: Apparent symbolic reference VARLIST not resolved.
ERROR: The text expression &VARLIST SPECIES contains a recursive reference to the macro variable VARLIST. The
macro variable will be assigned the null value.
This is because the macro variable &varlist in right side of the second %let statement was not declared before. To be clear, you can also replace the %local statement with an explicit initiating statement:
%let varlist=;
In this example, the %local statement and the %let statement simply do the same job and the choice is totally subject to programmers’ preference(well I prefer the later).
So, take home question: any comments on the following snippet to count the numbers of word in a string(also from Art Carpenter, 2004; sorry Carpenter, your books and papers are the most familiar sources for me to learn SAS macro programming):
%macro wordcount(list);
%local count;
%let count=0;
%do %while(%qscan(&list,&count+1,%str( )) ne %str());
%let count = %eval(&count+1);
%end;
&count
%mend wordcount;%put %wordcount(a b cd);