Working with SAS macro variables


Vinh Nguyen


July 28, 2011

Believe it or not, I recently had to use SAS for a simulation study because it was the only system available that could maximize the exact partial likelihood of a Cox proportional hazards model for tied data (ties=exact) in a reasonable amount of time for a data set of 2,000 observations. This was the first time I ran a simulation in SAS. I made use of the MACRO capabilities of SAS to write generic functions that could be used to repeat steps; I might blog about my overall experience some day. Today, I'll just write about one source of frustration that I had.

In writing my simulation study, I made use of Macro Variables (%let command) for the different scenarios I was investigating. After getting some unexpected results, I started debugging and then realized that whatever comes after the equal sign and before the semicolon of a %let statement is what the macro variable stores. For example, if I specify %let x = 2 + log(2) / λ ;, what gets stored in x is 2 + log(2) / λ. When I utilize &x, 2 + log(2) / λ gets substituted in the code (I incorrectly assumed this expression was evaluated), which can lead to unexpected results if it were used in mathematical expressions. For instance, if in a data step I do y = z / &x, then I might get something I wasn't expecting: z / 2 + log(2) / λ instead of z / (2 + log(2) / λ). I then thought I needed to use %EVAL or %SYSEVALF, but these functions only work with additions and not other mathematical functions (e.g., log). I also considered using CALL SYMPUTN but it could only be used in a DATA step. My solution for getting the right math is to always surround expressions with parentheses: %let x = (log(2) / λ). This way, it's safe to use &x as an entity.

To help with debugging and to see exactly how your code is running, I suggest the symbolgen option be turned on when macros are used:

options symbolgen ; /*show macro variable resolution*/