Google SAS Search

Add to Google

Wednesday, June 06, 2012

Comparing Macro Values

I was working on some SAS macro code today that I hadn't touched in quite a while. Actually, I haven't even been working on much SAS code for a while. So it was nice to get my mind back to the language I am most familiar with. I spent a good thirty minutes staring at a problem that was so simple that it should not have taken me long to figure it out.

A funny thing happens when you spend your development time hopping from language to language. You learn lots of techniques and ways of thinking, but you lose out on some of the day-to-day habits that coding in one language can instill in you.

I had a macro variable named &PATH that I was checking to see if it had a value of NULL. This path variable contained the fully-qualified name of a file (all the directory info). But I needed to assign it a default value (NULL) and check if anything was truly assigned.

%if &path ne NULL %then %do.....

I kept getting ERROR: A character operand was found in the %EVAL function of %IF condition where a numeric operand is required. The condition was: &path ne NULL

What the hell? That's about as straightforward a line of code as you could write! Well, since I've been hacking away on everything but SAS this last month, I immediately start questioning the language. Can I not use a mnemonic operator? Does it have to be "not ="?Is it something else in the code that's throwing it off? Is NULL a SAS keyword or something? Am I going senile? Blah blah blah.

And then it hit me. &PATH is a variable that's resolving to a value during execution. The value contains special characters (/var/path/more/path/etc) that are being evaluated badly. I needed to escape the value (or on SAS Macro parlance: quote the value) to hide it from the macro processor.

EDIT: Oops, I even used the wrong quoting function (sigh).

%if %nrstr(&name) ne NULL ...

Should be:
%if %quote(&name) ne NULL ...

So the SAS Macro day-to-day habit that I temporarily forgot: Do not trust the values of macro variables during execution. Unless you explicitly want the value to be processed, always wrap it with an appropriate quoting function.

Maybe my 30 minute loss will be your 30 minute gain. :)

4 comments:

  1. actually, shouldn't NRSTR or NRQUOTE also work, since they prevent it from being resolved?

    ReplyDelete
  2. Nope Gabe. For this you want run-time quoting. So %bquote (newer version of %quote) or %superq is what you want. I usally test like:

    %if %superq(name) ne %str() %then ...

    ReplyDelete
  3. Hi Gabe,

    That's a good question. The macro quoting functions cause all kinds of confusion. In my case I wanted the macro to resolve, I just wanted to hide the results from the macro as it was executing. If I had wanted to hide it during compile then I would have used NRSTR.

    Something like:

    %if %quote(&path) eq %str(/var/tmp) %then ...

    Notice &path get the execution time function and /vat/tmp gets the compile time function. The general rule of thumb is if YOU can see the value then it needs to be quoted with a compile time function. If the value is hidden in a macro variable then it needs to be hidden with an execution time function.

    Hope this helps. The documentation on this can be confusing as all hell.

    ReplyDelete
  4. Very usefull post!!

    Sometimes it's not easy tu use than macro functions.


    http://recursossassoftware.blogspot.com.es/

    ReplyDelete