scopesassas-macrosymbolic-references

Scope in SAS macro language. SAS not finding global variable defined in a macro. "WARNING: Apparent symbolic reference not resolved."


The goal

I have a macro called localOrGlobal that takes input and creates output. The output is printed to the log during the macro call. However, I want the user to be able to specify if the output should be made available as a global variable by using the parameter globalVar = 0.

The problem

Unfortunately, I cannot manage to make output available outside of the scope of the localOrGlobal call.

The code

/*Data for example purpose*/
data a;
    column = "exampleText";
run;

/*The macro. Set 'globalVar = 1' to make the 'output' available for later use.*/
%macro localOrGlobal(input, globalVar = 0);

    /* Control flow to define output as a local or global variable */
    %if globalVar = 0 %then %do;
            %local output;
        %end;
    %else %if globalVar = 1 %then %do;
            %global output;
        %end;

    /* Step that creates the output from the input*/
    proc sql;
        select * into : output separated by ' '
        from &input.;
    quit;

    /* Prints output to log, proving that output was created in the macro*/
    %put &output.;

%mend localOrGlobal;

/*Testing macro with output as a local variable*/
%localOrGlobal(a);

/*Expect this to fail since output should not exist outside of scope of the localOrGlobal call*/
%put &output.;

/*Testing macro with output as a global variable*/
%localOrGlobal(a, globalVar = 1);

/*Expect this to succeed since output be a global variable and exist outside the scope of the localOrGlobal call*/
%put &output.;

The error message

61         /*Expect this to succeed since output be a global variable and exist outside the scope of the localOrGlobal call*/
62         %put &output.;
WARNING: Apparent symbolic reference OUTPUT not resolved.
&output.

The expanded log

REDACTED LINES 1-23

24         /*Data for example purpose*/
25         data a;
26             column = "exampleText";
27         run;

NOTE: The data set WORK.A has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.01 seconds
      

28         
29         /*The macro. Set 'globalVar = 1' to make the 'output' available for later use.*/
30         %macro localOrGlobal(input, globalVar = 0);
31         
32             /* Control flow to define output as a local or global variable */
33             %if globalVar = 0 %then %do;
34                     %local output;
35                 %end;
36             %else %if globalVar = 1 %then %do;
37                     %global output;
38                 %end;
39         
40             /* Step that creates the output from the input*/
41             proc sql;
42                 select * into : output separated by ' '
43                 from &input.;
44             quit;
45         
46             /* Prints output to log, proving that output was created in the macro*/
47             %put NOTE: your output is below.;
48             %put &output.;
49         
50         %mend localOrGlobal;
2                                                          The SAS System                             17:43 Friday, October 23, 2020

51         
52         /*Testing macro with output as a local variable*/
53         %localOrGlobal(a);
MPRINT(LOCALORGLOBAL):   proc sql;
MPRINT(LOCALORGLOBAL):   select * into : output separated by ' ' from a;
MPRINT(LOCALORGLOBAL):   quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.02 seconds
      cpu time            0.01 seconds
      

NOTE: your output is below.
exampleText
54         
55         /*Expect this to fail since output should not exist outside of scope of the localOrGlobal call*/
56         %put &output.;
WARNING: Apparent symbolic reference OUTPUT not resolved.
&output.
57         
58         /*Testing macro with output as a global variable*/
59         %localOrGlobal(a, globalVar = 1);
MPRINT(LOCALORGLOBAL):   proc sql;
MPRINT(LOCALORGLOBAL):   select * into : output separated by ' ' from a;
MPRINT(LOCALORGLOBAL):   quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
      

NOTE: your output is below.
exampleText
60         
61         /*Expect this to succeed since output be a global variable and exist outside the scope of the localOrGlobal call*/
62         %put &output.;
WARNING: Apparent symbolic reference OUTPUT not resolved.
&output.
63         
64         GOPTIONS NOACCESSIBLE;
65         %LET _CLIENTTASKLABEL=;
66         %LET _CLIENTPROCESSFLOWNAME=;
67         %LET _CLIENTPROJECTPATH=;
68         %LET _CLIENTPROJECTNAME=;
69         %LET _SASPROGRAMFILE=;
70         
71         ;*';*";*/;quit;run;
72         ODS _ALL_ CLOSE;
73         
74         
75         QUIT; RUN;
76         

Expected solution

I will mark a solution as correct if it provides modifications to my code that prints output to the log when calling %put &output.; in 'open code' after running %localOrGlobal(a, globalVar = 1);.


Solution

  • You need to evaluate the value of a macro parameter by & resolving it.

    %if &globalVar = 0 %then %do;
    

    For logging macro variable values I recommend

    %put NOTE: &=output;