DATA Step, Macro, Functions and more

Call symput in a macro with/without parameter(s), and %global

Reply
Occasional Contributor
Posts: 9

Call symput in a macro with/without parameter(s), and %global

[ Edited ]

Consider the following data and two macros:

 

data mydata;
    input a b;
    datalines;
    1 2
    3 4
    ;
run;

 


%macro m1;
    data _null_;
        set mydata;
        if a=1 then call symput('x1', put(b, 1.));
    run;
%mend m1;

 

%macro m2(n=);
    data _null_;
        set mydata;
        if a=1 then call symput('x2', put(b, 1.));
    run;
%mend m2;

 

 

options mprint;

%m1;

%m2(n=1);

 

%put &x1;

%put &x2;

 

 

 

When I run this code, %put &x1 prints 2 to the log, as I expected. However, with the second macro--in which the only difference from the first is that it takes in a parameter (which isn't even used in the above example)--the result is instead a warning about the apparent symbolic reference not being resolved. I found a solution to get around this, namely adding %global x2 to the beginning of the macro. But my question is: Can anyone explain why macro m1 works fine, but macro m2 doesn't work unless the %global statement is added?

Super User
Posts: 23,937

Re: Call symput in a macro with/without parameter(s), and %global

I don't think either work as expected. Run both with a clean session and you should get the error overall. 

 

I would recommend using CALL SYMPUTwhich has a third parameter and allows you to create a global macro variable. 

SAS Super FREQ
Posts: 508

Re: Call symput in a macro with/without parameter(s), and %global

Let me second @Reeza's recommendation.  Since SYMPUTX came along, I never use SYMPUT.  Furthermore, SYMPUTX automatically does numeric to character conversions.

Super User
Posts: 2,041

Re: Call symput in a macro with/without parameter(s), and %global

Will this help?

 

Two rules control where CALL SYMPUT creates its variables:
  1. CALL SYMPUT creates the macro variable in the current symbol table available while the DATA step is executing, provided that symbol table is not empty. If it is empty (contains no local macro variables), usually CALL SYMPUT creates the variable in the closest nonempty symbol table.
  2. However, there are three cases where CALL SYMPUT creates the variable in the local symbol table, even if that symbol table is empty:
    • Beginning with SAS Version 8, if CALL SYMPUT is used after a PROC SQL, the variable will be created in a local symbol table.
    • If the macro variable SYSPBUFF is created at macro invocation time, the variable will be created in the local symbol table.
    • If the executing macro contains a computed %GOTO statement, the variable will be created in the local symbol table. A computed %GOTO statement is one that uses a label that contains an & or a % in it. That is, a computed %GOTO statement contains a macro variable reference or a macro call that produces a text expression. Here is an example of a computed %GOTO statement:
Occasional Contributor
Posts: 9

Re: Call symput in a macro with/without parameter(s), and %global

Posted in reply to novinosrin

Yeah, I think 1. is getting at the answer. Also just found this paper (http://www.lexjansen.com/phuse/2009/po/PO15.pdf) which seems to explain it:

 

"CALL SYMPUT may not create a GLOBAL macro variable when defined inside a macro definition. When we use CALL SYMPUT inside a macro definition, it will write the macro variable values into a local symbol table, if the macro has a non empty local symbol table. If macro has an empty local symbol table, the macro variable defined inside a macro, using CALL SYMPUT routine has global scope. The rules do not apply when you explicitly define them as GLOBAL or LOCAL."

Super User
Posts: 2,041

Re: Call symput in a macro with/without parameter(s), and %global

Yes Sir,  basically how I remember is all macro variables are created or overwritten(values) in the closest non empty symbol table unless there is a global macrovar with same name. Either way, when inside a macro wrapper as in your case, the parameter definition in itself makes your local symbol table non empty. Therefore, with parameter n= created a local macro var with a null value meaning 0 characters, however it is a still a valid value. When your call symput executes, the macro processor identifies the presence of the non empty local symbol table with N in it. Therefore, the macro var created by call symput goes straight to local symbol table of your second macro wrapper. I hope this explains a touch better. Cheers!

Super User
Super User
Posts: 8,261

Re: Call symput in a macro with/without parameter(s), and %global

Posted in reply to novinosrin

novinosrin wrote:

Yes Sir,  basically how I remember is all macro variables are created or overwritten(values) in the closest non empty symbol table unless there is a global macrovar with same name. Either way, when inside a macro wrapper as in your case, the parameter definition in itself makes your local symbol table non empty. Therefore, with parameter n= created a local macro var with a null value meaning 0 characters, however it is a still a valid value. When your call symput executes, the macro processor identifies the presence of the non empty local symbol table with N in it. Therefore, the macro var created by call symput goes straight to local symbol table of your second macro wrapper. I hope this explains a touch better. Cheers!


I like this explanation the best, except for one thing.  This:

unless there is a global macrovar with same name

should be rephrase to be something more like:

unless there is a EXISTING macrovar with the same name

 

Basically CALL SYMPUT() or %LET will use an existing macro variable before it creates a new macro variable.  It doesn't matter if it is global or if it exists in the scope of another macro that is running.  So if you make a local macro variable called FRED and call a subroutine macro that updates FRED without defining it as local it will update your local macro variable.

 

PROC Star
Posts: 1,471

Re: Call symput in a macro with/without parameter(s), and %global

Posted in reply to novinosrin

That's interesting @novinosrin.  I realize you copied the explanation from the docs, but regarding the three situations where SYMPUT will write to local symbol table, "even if it's empty":

  1. Beginning with SAS Version 8, if CALL SYMPUT is used after a PROC SQL, the variable will be created in a local symbol table.
  2. If the macro variable SYSPBUFF is created at macro invocation time, the variable will be created in the local symbol table.
  3. If the executing macro contains a computed %GOTO statement, the variable will be created in the local symbol table. A computed %GOTO statement is one that uses a label that contains an & or a % in it. That is, a computed %GOTO statement contains a macro variable reference or a macro call that produces a text expression.
     
    It seems to me that #1 is not an exception.  When you run PROC SQL, it creates (local) macro variables SQLOBS etc.  So the local symbol table is not really empty after that.  Similarly #2 is not an exception.  When you define a macro with /parmbuff it creates an automatic macro variable SYSPBUFF in the local symbol table, so it's not empty.
     
    I have no idea why a computed %GOTO would change the behavior of CALL SYMPUT (as it does).  I would suspect that there may be some hidden (?) macro variable created in the local symbol table, for some reason.  Any thoughts as to a better explanation?
     
     
     
     
     
Super User
Posts: 2,041

Re: Call symput in a macro with/without parameter(s), and %global

@Quentin  Sir, Briiliant and Great catch!. Hmm, will have to dig in seriously to have an explanation for the computed goto. 

 

As the definition says,  A text expression that generates a label in a %GOTO statement is called a computed %GOTO destination.

Here are my crazy guesses-

1. May be the & or % trigger in the expression is a nested macro call that at compile time made the local symbol table non empty.

2. The text expression without a macro trigger prolly wouldn't be relevant to affect the symbol table

3. So the correlation perhaps would have to be %Goto has to be in  macro wrapper, and the label that goes with it viz. if is a result of macro processor resolution hitting the SASMacr catalog or symbol table 

Thank you for waking me!

 

 

 

Super User
Super User
Posts: 9,799

Re: Call symput in a macro with/without parameter(s), and %global

Do bear in mind that creating global macro variables in levels of macro down can lead to some really hard to debug, obfuscated code.  There is never a need to do such a thing.  Global macro varaibles are just that, macro varaibles available to the whole session and thus should be setup at session start.  Creating global macros within code shows a distinct lack of planning, and poor design.

Ask a Question
Discussion stats
  • 9 replies
  • 336 views
  • 6 likes
  • 7 in conversation