Dynamic Macro Loops in SAS - No More Double Ampersand
Dynamic code creation is a strength with SAS, but can also cause readability problems. Try dynamically creating the upper limit of a %Do, instead of using a
Double ampersand macro variables make me queasy, I’ve even came across a triple before; I was very nearly sick in my mouth. If I saw a working
&&&¯oVariable. then I’d probably go projectile.
The Problem with &&
SAS can be tricky enough at times, figuring out what parts of code are processed or dynamically created by the macro pre-processor, and what will be executed by the engine itself. I love a SAS macro, but adding another level of dynamically generated code through all this
&&baseName.&NthOne. carry-on is asking for trouble.
I like an approach with a clear list of inputs (i.e. a SAS data set), that can still be looped over dynamically using only single ampersand variables.
My alternative is by no-means fool proof, but at least for the things I find myself doing in SAS, it reads better and makes more sense.
%Macro loop(); Proc SQL noPrint; Select var Into :items separated by "|" /* 1. */ From aDataSet Quit; %Do itemNumber = 1 %to %sysFunc(countW(&items., |)); * 2. ; %Let item = %scan(&items., &itemNumber, |); * 3. ; %Put item=&item.; * 4. ; %End; %MEnd; %loop;
- Get the names of things you want to iterate over into a data set first. Use a delimiter on the into statement that won’t appear in your
itemlist. At the end of the
Proc SQL, all the the items from
varwill be in a single macro variable -
- Dynamically create the upper limit of the
%Dostatement, by counting the number of items in the list, as separated by the delimiter.
- On each iteration of the loop, a new
&itemvariable will be made, by scanning the list of items, for the ith item (again, based on the delimiter).
- Do something useful with this particular item!
- Delimiter selection is key, I tend to use the pipe symbol “|” because it doesn’t show up in file system paths or most other names.
- When doing a lot with this, beware of maximum macro variable length - 65534 characters. If you implement this and then bump up against the limit, it’s an easy swap to count the number of items in the
Proc SQLand then select the ith item into a macro variable during the
symputin a data step).