2 min read

Localize Your Macro Variable? Mostly Not Needed or Do It If You Only Want to Initiate It


[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 ;
%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);
%mend wordcount;

%put %wordcount(a b cd);