People who are following the reverb10 blogs would no doubt be disappointed by today’s post because it has absolutely nothing to do with finding my compass in life, unless life’s compass is possibly nested in a SAS macro. Since I started this blog to write down things I was sure I would want to remember later, today’s post fits my life (or, at least blog) goal exactly.
Today, I decided to RTFM.
Various statistical applications differ in their style for manuals. Stata is okay to use for getting statistical results but the documentation tends to be very terse.
“These are numbers. Take the integral of the factorial of the determinant of the matrix which results from the inverse of the product of covariance matrix and the Y vector from the equation you will be solving this time next year. Then the universe explodes and you have your answer.”
SAS goes in the other direction, pretty much starting each chapter with the discovery of the number two by a Neanderthal named Og, proceeding through proofs going back to Euclid and up to the latest Joint Statistical Meetings.
Most of the SPSS documentation I have seen was really basic.
One is a number. Two is a bigger number. Statistics uses numbers like one and two. These are what statisticians refer to as ‘numbers’.
I seem to write a lot about SAS and I was planning on broadening my horizons, but I happened to be interested in macros today … I’ve used SAS macros as needed for years, even took a course a decade or so ago, read articles to solve problems as I came across them, but never read the manual from beginning to end, so I figured I missed a few things here and there. So, this afternoon, I sat down and started at page 1. I ran across this bit about nesting, global and local macros and I had to think for a minute until it was obvious.
The points being made were that:
1. There are global macro variables and local macro variables. Global variables are available at any time during your program. Local variables are only available during the macro in which they are created BUT …
2. If a variable by a given name is already created, and then you use that same variable name within a macro, it will not create a new one, it will replace the value in the existing variable.
Here is what it said in the manual
“The same rule applies regardless of how many levels of nesting exist. Consider the following example:
The macro processor generates these statements:
My first thought was – huh? Then I realized
- OK, &new is already created as a global macro variable before the macro, %name3, even exists.
- When %name3 has a %LET statement using a variable named &new, it simply changes the name of the existing macro variable.
- This is the part that threw me at first — the macro variable &old is created within the macro %name3. So it is local to that macro. We are still in %name3, so we have the variable &old available to us.
- The macro %conditn executes. It CHANGES the value of the variable &old. It also creates an &cond variable which evaporates as soon as the macro ends because it is a strictly local variable to %conditn.
- When %name3 executes we have access to variable &new as it is a global variable. It has the value to which it was changed in this macro. We have access to the variable &old as it is a variable local to the macro that is executing right now, name3. It has the value that it was changed to by macro %conditn, which executed before our DATA step. Not being able to resolve the reference to &cond it simply produces text that says “&cond” .
What have we learned here?
The first, most obvious piece of advice is not to re-use the same macro variable names within a program unless you really do want the global or nested macro variable to be changing the value. I mean, it’s not like we’re short on potential variable names here. They don’t even have to be actual words. You can name your macro variable ushnakatz if you want.
The second is to be aware of how SAS processes macro variables. I can see uses where I might want to create a variable and then change it within a macro so that I can have one macro that generates reports on sales, another on inventory, etc. and uses all the same procedures otherwise. Something like that %conditn macro, but working.