Macro Myth: The closest non-empty symbol table

2
Robert Virgile
Robert Virgile

This SAS tip is from Robert Virgile and his book “SAS Macro Language Magic: Discovering Advanced Techniques”.

We hope you find this tip useful. You can also read an excerpt from Virgile’s book.

When CALL SYMPUT creates a new macro variable, it places that variable in “the closest non-empty symbol table.”  But what does that mean?  And why does CALL SYMPUT exhibit such unusual behavior?

Consider first the outcome.  In the simplest situation, the macro %A generates a complete DATA step that includes CALL SYMPUT.  When %A executes, CALL SYMPUT would replace an existing macro variable if it could.  But assuming that CALL SYMPUT must create a new macro variable &ABC:

  • If the local symbol table for %A already contains any macro variable, CALL SYMPUT creates a local macro variable &ABC.
  • If the local symbol for %A is empty, CALL SYMPUT creates &ABC in the global symbol table.

We know that Rube Goldberg did not invent the macro language.  So why does CALL SYMPUT behave this way?  We’ll come back to that question after reviewing one more example.

Next, consider a more complex situation.  Using the same definition of %A, a program uses %B to call %A.  Now there are three symbol tables to consider:  the global symbol table, as well as local symbol tables for both %A and %B.

When %B calls %A, the closest symbol table is the local symbol table for %A.  In that case:

  • If the local symbol table for %A already contains any macro variable, CALL SYMPUT creates &ABC in the local symbol table for %A.

However, what if the local symbol table for %A is empty?  In that case:

  • If the local symbol table for %B already contains any macro variable, CALL SYMPUT creates &ABC in the local symbol table for %B.
  • Otherwise, CALL SYMPUT creates &ABC in the global symbol table.

Well, those are the rules and that is the behavior.  But why?  No other macro language tool exhibits this behavior (with the possible exception of CALL SYMPUTX).  Does this make any sense at all?

One key feature explains these results.  There is no such thing as an empty symbol table.  The phrase “closest non-empty symbol table” is misleading because all symbol tables are non-empty.  Why?  Because the software doesn’t create a symbol table until it is needed in order to hold a macro variable.

Certainly the global symbol table is never empty.  It may not contain user-defined macro variables, but it always contains a set of automatic macro variables.

Similarly, local symbol tables are never empty.  (Yes, this means that all the descriptions in the first half of this post are misleading.  They accurately describe the outcome, but inaccurately describe the process.)  Here is an example that illustrates the true process:

%macro A;
   data _null_;
      call symput('before', 'before value');
   run;
   %local abc;
   data _null_;
      call symput('after', 'after value');
   run;
%mend A;
%A

As %A begins to execute, there is no local symbol table.  When the first DATA step executes, CALL SYMPUT has no choice.  It must place &BEFORE in the global symbol table.

Next, the %LOCAL statement executes, telling the software to place &ABC in the local symbol table for %A.  This forces the software to create a local symbol table.  When the second DATA step executes, CALL SYMPUT places &AFTER in the first symbol table it finds, which is the local symbol table for %A.

So the bottom line is this.  The term “closest non-empty symbol table” is misleading.  There are no empty symbol tables.  CALL SYMPUT searches for any existing symbol table.  The search moves from local to global, and CALL SYMPUT uses the first symbol table it finds.

For more information about the macro language and the magic you can create with it, check out “SAS Macro Language Magic: Discovering Advanced Techniques”.

Share

About Author

Cindy Puryear

Senior Marketing Specialist, SAS Publications

2 Comments

  1. This is a great explanation (of course, wouldn't expect any less from Bob Virgile!) Still, it begs the question of why CALL SYMPUT() cannot create a local symbol table. Is it just an accident of history? Note that %LET can create a local symbol table, and PROC SQL with INTO: can create a local symbol table. And of course CALL SYMPUTX() can as well. I've been curious about the *why* for years...

    • Quentin,

      I asked Bob about your post and this was his reply:

      My best guess is, to borrow that phrase, this is just an accident of history. SAS is very good about making the software versions backwards compatible, and so would be reluctant to change the behavior of an existing tool. The "fix" (if you choose to use that term) was embodied in CALL SYMPUTX. That way, you get the ability to have a DATA step create a local symbol table, while leaving the existing tool intact.

      Bob V.

Back to Top