SAS宏执行顺序

SAS宏执行顺序,sas,sas-macro,Sas,Sas Macro,我使用宏锁定数据集: %macro lockTab(member=APP_DATABASE,timeout=30,retry=500); %global LOCK_&member; %let LOCK_&member = ; %local starttime; %let starttime = %sysfunc(datetime()); %put try to lock &member.: &starttime; %do %until (&

我使用宏锁定数据集:

%macro lockTab(member=APP_DATABASE,timeout=30,retry=500);
  %global LOCK_&member;
  %let LOCK_&member = ;
  %local starttime;
  %let starttime = %sysfunc(datetime());
  %put try to lock &member.: &starttime;
  %do %until (&syslckrc = 0
       or %sysevalf(%sysfunc(datetime()) > (&starttime + &timeout)));
      lock APPLIB.&member.;
      %put syslckrc=&syslckrc;
      %if &syslckrc > 0 %then %let rc=%sysfunc(sleep(&retry.));
  %end;
  %let endtime = %sysfunc(datetime());
  %put end of try to lock &member.: &endtime;
  %if &syslckrc <= 0 %then %do;
      %let LOCK_&member = LOCK;
  %end;
  %else %do;
    %let _appRetcode = 12;
    %let _appErrtext = Database is locked.;
  %end;
    %put ende Locktab: appretcode: &_appRetcode;
    %put ende Locktab: syslckrc: &syslckrc;
%mend;
这是我的日志:

NOTE: 1 record was written to the file _WEBOUT.
      The minimum record length was 42.
      The maximum record length was 42.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


SYMBOLGEN:  Macro variable _APPRETCODE resolves to 0
EYECATCHER 0
SYMBOLGEN:  Macro variable MEMBER resolves to APP_DATABASE
SYMBOLGEN:  Macro variable MEMBER resolves to APP_DATABASE
SYMBOLGEN:  Macro variable MEMBER resolves to APP_DATABASE
                                                                                          The SAS System

SYMBOLGEN:  Macro variable STARTTIME resolves to 1834989255.00056
try to lock APP_DATABASE: 1834989255.00056
SYMBOLGEN:  Macro variable MEMBER resolves to APP_DATABASE
ERROR: A lock is not available for APPLIB.APP_DATABASE.DATA.
ERROR: Lock held by process 1360575.
SYMBOLGEN:  Macro variable SYSLCKRC resolves to 70031
syslckrc=70031
SYMBOLGEN:  Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN:  Macro variable RETRY resolves to 500
SYMBOLGEN:  Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN:  Macro variable STARTTIME resolves to 1834989255.00056
SYMBOLGEN:  Macro variable TIMEOUT resolves to 30
SYMBOLGEN:  Macro variable MEMBER resolves to APP_DATABASE
ERROR: A lock is not available for APPLIB.APP_DATABASE.DATA.
ERROR: Lock held by process 1360575.
.......
end of try to lock APP_DATABASE: 1834989285.01467
SYMBOLGEN:  Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN:  Macro variable _APPRETCODE resolves to 12
ende Locktab: appretcode: 12
                                                                                          The SAS System

SYMBOLGEN:  Macro variable SYSLCKRC resolves to 70031
ende Locktab: syslckrc: 70031
为什么EYECATCHER在我的宏输出之前打印出来

我希望首先输出宏lockTab,然后是“eyecatcher12”。 ""

%调试给出:(范围/变量/值)全局/_APPRETCODE/12

只是一个想法:
你试过在宏调用后加分号吗?缺少分号通常会带来一些问题。即使宏看起来运行正常。

您提供的代码是否包装在父宏中

我能够重现这种行为,但只能在另一个宏中重现

示例代码:

%macro x;
  %macro demo1(); %put see;  %mend;
  %macro demo2(); %put this; %mend;
  %demo1          %put here; %demo2()
%mend;
%x
其中打印:

here  
see
this
see  
here
this
与之形成对比的是:

%macro demo1(); %put see;  %mend;
%macro demo2(); %put this; %mend;
%demo1          %put here; %demo2()
其中打印:

here  
see
this
see  
here
this
这确实似乎是一个解析器错误,或者至少是一个不一致性


我建议将子宏定义移到父包装器之外。我还建议始终使用括号定义宏,并按括号调用宏。

我认为问题与解析器决定宏调用何时结束有关。如果宏是用参数定义的(即使参数列表为空),则宏调用不会在空白处结束。它以右括号结束。它还将在SAS语言标记(包括SAS语言分号)或另一个宏调用处结束

这就是为什么像下面这样丑陋的东西会起作用:

%macro doit (x=) ;
  %put &=x  ;
%mend doit;
%doit     (x=3)
改变@Allan的示例,如果demo1和demo2的定义没有参数,那么代码会工作,因为demo1和demo3的调用将由空格触发

358  %macro demo1; %put 1 first; %mend;
359  %macro demo3; %put 3 third; %mend;
360  %macro x;
361    %demo1
362    %put 2 second;
363    %demo3
364  %mend x;
365  %x
1 first
2 second
3 third
但是,如果使用参数列表定义了%demo1,则空格不足以结束宏调用。即使是%PUT语句也不会结束宏调用。SAS一直在寻找参数列表,直到它命中调用%demo3,并意识到“好吧,必须完成第一个宏调用。”此时%PUT语句已经执行

366  %macro demo1(); %put 1 first; %mend;
367  %macro demo3; %put 3 third; %mend;
368  %macro x;
369    %demo1
370    %put 2 second;
371    %demo3
372  %mend x;
373  %x
2 second
1 first
3 third
作为证据,请考虑如下。看起来我正在将VAR参数传递给%X(它没有定义参数)。但是%demo1的调用仍然在愉快地等待参数列表,并且它接受了它。这表明%PUT语句不足以结束对%demo1的调用

404  %macro demo1(var=); %put 1 first; %put &=var ;%mend;
405  %macro x;
406    %demo1
407    %put 2 second;
408  %mend x;
409  %x(var=hello)
2 second
1 first
VAR=hello

我很难记住伊恩·惠特洛克教给我的所有规则,有时我害怕把一条我记错了的规则归咎于他。但我很有信心,他认为所有宏都应该至少有一个参数(他对宏的定义是“参数化的代码单元”),并且宏调用应该总是以括号结束,即使它是接受默认值的空参数列表,即%doit()。这确保了宏在预期的情况下执行,而不添加SAS语言分号,这有时会把事情搞砸。

我被告知在调用宏时不要使用分号。如果我调用“%lockTab()”而不是“%lockTab”,它会工作。所以它看起来和括号有关。但是为什么呢?解析器错误?好的,那么您是通过在宏调用之后添加括号来实现的,就像这样
%lockTab()
?不知道为什么会这样。但如果你能让它工作,那就太好了!在宏调用之后包含分号肯定不是一个好的做法,因为它们可能会导致错误。考虑:
%macro x();y=x;%修理数据;如果为0,则为%x();否则1=1;运行
将由于if-else逻辑过早终止而导致错误。@AllanBowe很好,您已经指出了这一点。在过去的10年里,我经常使用宏,从未遇到过由此引起的错误。您提供的示例是有效的,但我在实践中从未遇到过这样的用例。