6

在我的代码中,我有几个宏。宏 A 是主宏。然后宏 A 调用宏 B,宏 B 又调用宏 C。

在 SAS 中,我是否必须按倒序定义它们?换句话说,我是否必须先定义宏 C,然后定义宏 B,最后定义宏 A?还是因为 SAS 在实际执行运行宏的命令之前读取了所有代码,这是否重要?就此而言,我可以发出命令将宏作为代码中的第一条语句运行,然后在命令下方定义宏吗?

谢谢!

4

4 回答 4

3

首先,您必须在调用它之前定义一个宏。

其次,只要您事先加载了宏,调用宏的位置并不重要。

详细说明您的问题:自动调用库是您的朋友。如果您的 SAS 管理员不允许您将宏放入自动调用库中,您可以像这样附加自动调用:

filename mymacros 'c:\mysas'; 
/*this defines the directory you have stored your macros*/

options sasautos=(sasautos mymacros) mautosource; 
于 2009-02-11T17:48:46.550 回答
3

宏必须在调用之前定义。出于性能原因,最好不要在另一个宏中定义一个宏——如果这样做,那么每次调用外部宏时都会重新定义它。以下工作正常:

%macro a;
  %put a;
  %b
%mend a;

%macro b;
  %put b;
  %c
%mend b;

%macro c;
  %put c;
%mend c;

%*-- %a is main --*;
%a
/* on log
a
b
c
*/
于 2009-02-22T17:48:20.330 回答
1

您必须在调用之前定义一个宏,因此带有“%A”的行需要遵循宏 A 的定义。其他宏定义的顺序无关紧要,只要它们在调用之前定义即可。通常,在我的程序中,我会像您描述的那样设置一个主宏,然后程序的最后一行调用这个宏。

另一个需要考虑的选项是设置一个宏自动调用库,其中包含许多宏的定义。这对可重用宏最有效,因此您不必在每个程序中重新定义它们。

于 2009-02-11T16:16:17.707 回答
0

SAS中的宏代码有两个方面需要定义:被编译的宏代码和宏参数:

宏代码:

宏代码本身非常简单,当%macro遇到令牌时,SAS 系统开始编译 SAS 宏并继续编译,直到遇到%mend令牌。您可能遇到的唯一真正问题是,如果您更新了宏代码并且在执行之前没有重新编译它——在这些情况下,它仍然会运行它在宏库中的旧版本。通过扩展,如果您尝试编译一个调用另一个尚未定义的宏的宏,那么您将收到一个错误。由于这些原因,它们需要按照调用顺序进行编程(如下例所示:%level3 在 %level2 之前,在 %level1 之前)

宏变量: 定义宏变量时有两个作用域:全局和局部。定义后,可以随时随地访问全局变量。但是,局部变量仅在执行定义它的宏期间本地存在。通过扩展,如果定义了局部变量的宏调用了任何其他宏,则仍然可以访问局部宏变量:

工作示例:

在以下示例中,宏以相反的顺序定义,以防止 SAS 返回明显调用宏警告。

下图说明了以下示例中以下宏的结构:

|-----------------------------|
|GLOBAL                       |
|  |------------------------| |
|  |LEVEL1                  | |
|  |  |-------------------| | |
|  |  |LEVEL2             | | |
|  |  |  |--------------| | | |
|  |  |  |  LEVEL3      | | | |
|  |  |  |--------------| | | |
|  |  |-------------------| | |
|  |------------------------| |
|-----------------------------|

编译嵌套宏:

 %macro level3 ;
  %put **** START LEVEL3 **** ;
  %local G1;
  %let G1=Local ;

  %do i=1 %to 2 ;
    %put In the macro do loop I=&i ;
  %end ;

  %put The value of I at level3 is: &I ;
  %put Are we accessing global or local G1 variable here: &G1 ;

  %put **** END LEVEL3 ****;
%mend level3 ;


 %macro level2 ;
  %put **** START LEVEL2 **** ;
  %*global L1 ; *<-- this would produce an error because the variable name has already been added to the local scope in %level1 ;

  %put Are we accessing global or local G1 variable here: &G1 ;
  %put Can we access local variables here: &L1 ;

  %level3 ;

  %put The value of I in level2 is: &I ;
  %put **** END LEVEL2 ****;
%mend level2 ;

编译顶层宏(依次调用上述两个宏)并运行它:

%let G1=Global;
%macro level1 ;
  %put **** START LEVEL1 **** ;
  %let L1=Yes;

  %put Are we accessing global or local G1 variable here: &G1 ;
  %put Can we access local variables here: &L1 ;

  %level2 ;

  %put The value of I outside of the local macro is: &I ;
  %put Are we accessing global or local G1 variable here: &G1 ;

  %put **** END LEVEL1 ****;
%mend level1 ;
%level1 ;

查看日志时需要注意的几点:

  • 在 %level3 之外,&I 返回宏变量不存在的警告
  • 在%level3内,调用&G1时,返回%level3本地范围内存储的值。一旦在%level3之外,则返回全局存储的值
于 2015-05-26T13:21:47.100 回答