SAS 宏语言中的范围。SAS 找不到宏中定义的全局变量。 "WARNING: Apparent symbolic reference not resolved."



目标

我有一个名为localOrGlobal的宏,它接受input并创建output。在宏调用期间,output被打印到日志中。但是,我希望用户能够通过使用参数globalVar = 0指定output是否应作为全局变量可用。

问题

不幸的是,我无法使outputlocalOrGlobal调用的范围之外可用。

代码

/*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.;

错误消息

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.

展开的日志

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         

预期解决方案

如果解决方案在运行%localOrGlobal(a, globalVar = 1);后以"打开代码"调用%put &output.;时对我的代码进行了修改,并将output打印到日志中,则我会将其标记为正确的。

您需要通过&解析来评估宏参数的值。

%if &globalVar = 0 %then %do;

对于记录宏变量值,我推荐

%put NOTE: &=output;

只需在调用宏之前定义宏变量,就可以在不修复宏的情况下修复程序。

%let output=before macro call; 
%localOrGlobal(a, globalVar = 1);
%put &=output;

这是因为文字文本globalVar永远不会等于文本0或文本1。因此,%local%global语句都不会运行。您需要使用&globalVar来使用globalVar的值。

如果您当前的逻辑有效,则将GLOBALVAR视为三级逻辑。0表示将其设为本地,1表示将其设置为全局,其他任何内容都表示遵循SAS的正常作用域规则。但是,如果从另一个已将输出定义为本地宏变量的宏调用此宏,则为输出发出%GLOBAL语句将导致错误。您可以通过测试是否已经定义了输出来解决这个问题。

试试这样的逻辑。

%if &globalVar = 0 %then %local output;
%else %if (&globalVar = 1) and (not %symexist(output)) %then %global output;

最新更新