美文网首页
258:macro base(六)---宏嵌套

258:macro base(六)---宏嵌套

作者: SASPRO的打工人生活 | 来源:发表于2023-08-02 14:46 被阅读0次

每天进步一点点,幸福生活快一点。

当一个宏里面还嵌套一个或者多个宏,这个叫做嵌套宏。先看一个简单的例子:

%let dsn=sashelp.cars;

%macro mac(dsn=,obs=);
     data test;
        set &dsn;
    run;

     data test2;
        set test(obs=&obs);
    run;
%mend;
%mac(dsn=&dsn,obs=5);

如果数据集的名称已经存储在宏变量中,则可以重写宏调用以利用该存储值。

以上面的程序为例,在调用宏mac之前,括号里面的任何宏引用(macro references)必须先被解析,所以&dsn会被解析成sashelp.cars,之后就变成了%mac(dsn=sashelp.cars,obs=5);

下面看一个嵌套宏:

%macro precomp(sex=,no=no);
options &no.mprint &no.symbolgen &no.mlogic;    /*①*/

data test;
    set sashelp.class;
    if sex=&sex;
run;

* Create the location data set;
%locate(sex=&sex,no=&no)      /*②*/

data test2;
    set sashelp.cars;
run;
%mend precomp;

%macro locate(sex=, no=no);
options &no.mprint &no.symbolgen &no.mlogic;    /*③*/

data test3;
    set sashelp.class;
    if sex=&sex;
run;

%mend locate;

%precomp(sex="F");

在上面的程序中,&no宏参数用的是默认的值,也就是NO,
①位置,在OPTION语句能执行之前,&no必须被解析,也就是NO,因此这句话变成了options nomprint nosymbolgen nomlogic;

②位置,在宏locate被调用之前,宏引用(macro references) &SUBJECT and &NO必须被解析,所以%locate(sex=&sex,no=&no)被解析成%locate(subject=1234, no=no)

③位置,当%locate被执行的时候,&NO被解析成NO,对应的options也变成了options nomprint nosymbolgen nomlogic;

定义宏的顺序并不重要,只要每个宏都是在调用之前是已经定义的。

%macro precomp(sex=,no=);


data test;
  set sashelp.class(obs=&no);
  if sex=&sex;
run;

* Create the location data set;
%locate(sex=&sex,obs=&no)

data test2;
  set sashelp.cars;
run;
%mend precomp;

%precomp(sex="F",no=7);

%macro locate(sex=, no=);

data test3;
  set sashelp.class(obs=&no);
  if sex=&sex;
run;

%mend locate;

比如我在定义宏locate之前就调用了宏precomp,这时候肯定会出错的


image.png

Note:

在我将这上面的程序复制到SAS的时候,发现报错了,显示这个no打错了,但是我明明是从SAS复制到这上面,然后又复制到SAS的时候出错了,所以你们如果复制出现问题的话,建议重新手打一遍,我记得以前的时候也出现了这样的情况,明明肉眼看是长得一样,可就是出问题。


image.png image.png

同时发现这个set莫名其妙地变红了,发现data前面好像插入了什么符号,键盘右键移动一格的时候,光标并没有向右移动一格,好像卡住了一样,了解这个的欢迎解释一下。可能是这上面的代码编辑器会自动插入什么字符。

image.png

如果你第一次运行过locate这个宏的时候,其实SAS已经编译完成了,所以第二次你再跑宏precomp的时候,就可以正常运行了,但是这样编程肯定是有问题的。

%macro precomp(sexmain=,obs=);


/*调用precomp里的宏参数*/
%locate(sex=&sexmain,no=&obs)

data test2;
  set sashelp.cars;
run;
%mend precomp;

%macro locate(sex=, no=);

  data test3;
    set sashelp.class(obs=&no);
    if sex=&sex;
  run;

%mend locate;

%precomp(sexmain="F",obs=7);

在precomp里的参数不需要和locate保持一致,只要保证你调用的是正确的宏参数就行了,就像下面加粗部分%locate(sex=&sexmain,no=&obs)。同时,你调用宏precomp的时候也就调用了宏locate。

同时需要注意的是%locate(sex=&sexmain,no=&obs)里面的&sexmain和&obs是先被解析,之后才是宏locate被调用。
详细解析一下这两个宏执行的步骤:

①:当我调用%precomp(sexmain="F",obs=7)的时候,因为不包含任何宏引用,所以不需要一个解析的过程直接就宏变量sexmain接收到值"F",宏变量obs接收到值7;

②:调用%locate(sex=&sexmain,no=&obs)的时候,&sexmain和&obs先解析成对应的值;
③:宏locate被调用

④:宏变量sex接收到值"F",宏变量no接收到值7;

⑤:之后编译locate里面的这段程序,

data test3;
    set sashelp.class(obs=&no);
    if sex=&sex;
  run;

对应的宏变量被解析成对应的值,之后才能被运行。
对应的流程图解释可以参照下面这张图,注意我上面的①完成后应该有一个宏precomp展开的过程,就是下面红框这部分

image.png

我觉得了解宏执行的顺序,跟以前一篇文章了解宏变量解析的顺序是一样的,对你debug宏有很大帮助,你只有知道宏是怎样运行,才可能知道你的程序在哪出问题。
The end。

相关文章

  • 宏(Macro)指的是 Rust 中一系列的功能 声明(Declarative)宏, 使用macro_rules!...

  • 模板宏

    声明宏 {% macro 宏的名字(参数) %}​内容{% endmacro %} 调用宏 {{ 宏的名字(参数...

  • 数据分析师-Week16

    1.调用rar解压.rar 2.在宏(macro)中高亮显示关键字 3.用宏macro处理参数并返回结果

  • JS事件循环机制之宏任务/微任务

    宏任务(macro-task)macro-task.png 微任务(micro-task)micro-task.p...

  • 宏指令(Macro)

    人类宇宙,克莱因瓶 衡宇宙,克莱因瓶 量子计算机,瓶塞 瓶外,无限 无限侵入有限时空, 所以我们将历经无数种可能 ...

  • this.$nextTick的那些事

    宏任务macro task: setTimeout、MessageChannel、postMessage、setI...

  • 191:macro base(一)

    最近真的感觉身心疲惫,一方面感觉来自公司不断增加的压力,这个就不多说了;另一方面就是各个项目的不断切换和单个项目的...

  • iOS基础-宏定义

    宏定义 Macros A macro is a fragment of code which has been g...

  • 二、输出顺序(console.log、settimeout、pr

    macro-task(宏任务):包括整体代码script,setTimeout,setIntervalmicro-...

  • C语言-函数式宏

    函数式宏 函数式宏(function-like macro)较之对象式宏可以进行更复杂的代换。 函数和函数式宏 函...

网友评论

    本文标题:258:macro base(六)---宏嵌套

    本文链接:https://www.haomeiwen.com/subject/nzfppdtx.html