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 && and & combination.

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 &&&&macroVariable. 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.

One alternative

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;

  1. 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 item list. At the end of the Proc SQL, all the the items from var will be in a single macro variable - &items.
  2. Dynamically create the upper limit of the %Do statement, by counting the number of items in the list, as separated by the delimiter.
  3. On each iteration of the loop, a new &item variable will be made, by scanning the list of items, for the ith item (again, based on the delimiter).
  4. Do something useful with this particular item!

Tripping points

  • 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 SQL and then select the ith item into a macro variable during the %Do (using _N_ and symput in a data step).