SAS 宏语言中的作用域。 SAS 未找到在宏中定义的全局变量。 "WARNING: Apparent symbolic reference not resolved."
Scope in SAS macro language. SAS not finding global variable defined in a macro. "WARNING: Apparent symbolic reference not resolved."
目标
我有一个名为 localOrGlobal
的宏,它接受 input
并创建 output
。 output
在宏调用期间打印到日志中。但是,我希望用户能够通过使用参数 globalVar = 0
.
来指定 output
是否应该作为全局变量使用
问题
不幸的是,我无法使 output
在 localOrGlobal
调用范围之外可用。
代码
/*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
预期的解决方案
如果解决方案对我的代码进行了修改,在 运行 之后调用 'open code' 中的 %put &output.;
时将 output
打印到日志,我会将其标记为正确的 %localOrGlobal(a, globalVar = 1);
.
您需要通过&
解析宏参数来评估它的值。
%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 视为 tri-level。 0 表示将其设为本地,1 表示将其设为全局,其他任何表示遵循 SAS 的正常范围规则。但是,如果您从另一个已将输出定义为局部宏变量的宏调用此宏,则为输出发出 %GLOBAL 语句将导致错误。您可以通过测试是否已定义输出来解决此问题。
试试这样的逻辑。
%if &globalVar = 0 %then %local output;
%else %if (&globalVar = 1) and (not %symexist(output)) %then %global output;
目标
我有一个名为 localOrGlobal
的宏,它接受 input
并创建 output
。 output
在宏调用期间打印到日志中。但是,我希望用户能够通过使用参数 globalVar = 0
.
output
是否应该作为全局变量使用
问题
不幸的是,我无法使 output
在 localOrGlobal
调用范围之外可用。
代码
/*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
预期的解决方案
如果解决方案对我的代码进行了修改,在 运行 之后调用 'open code' 中的 %put &output.;
时将 output
打印到日志,我会将其标记为正确的 %localOrGlobal(a, globalVar = 1);
.
您需要通过&
解析宏参数来评估它的值。
%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 视为 tri-level。 0 表示将其设为本地,1 表示将其设为全局,其他任何表示遵循 SAS 的正常范围规则。但是,如果您从另一个已将输出定义为局部宏变量的宏调用此宏,则为输出发出 %GLOBAL 语句将导致错误。您可以通过测试是否已定义输出来解决此问题。
试试这样的逻辑。
%if &globalVar = 0 %then %local output;
%else %if (&globalVar = 1) and (not %symexist(output)) %then %global output;