CLisp 24:宏的本质也是函数

       定义了一个宏,可以用macroexpand-1查看宏的展开式,这里介绍一种新的方法,有助于理解宏的本质。

 

 [5]> (defmacro moo(x y)           首先定义一个宏,非常简单

`(format t "~A : ~A~%" ,x ,y))

MOO

[6]> (moo 'asdf 'er)              执行宏,就是将输入的两个参数打印出来

ASDF : ER

NIL

 

[7]> (macroexpand-1 '(moo 'asdf 'ar))         查看宏的展开式

(FORMAT T "~A : ~A~%" 'ASDF 'AR) ;

T

 

下面开始介绍新的方法,函数macro-function是关键,它能够获取一个宏的实现,也就是一个函数。下面就是取出来的函数,看起来很复杂,下面一行行地解读。

[8]> (setf moo-fun (macro-function 'moo))

#<FUNCTION MOO (SYSTEM::<MACRO-FORM> SYSTEM::<ENV-ARG>)

       函数的名称也叫MOO,它有两个参数,第一个是调用宏时的整个表达式,包括宏名和参数,没有研究第二个参数,应该用来表示环境变量。

  (DECLARE (CONS SYSTEM::<MACRO-FORM>)) (DECLARE (IGNORE SYSTEM::<ENV-ARG>))

  (IF (NOT (SYSTEM::LIST-LENGTH-IN-BOUNDS-P SYSTEM::<MACRO-FORM> 3 3 NIL))

       检查调用宏时输入的参数个数是否正确,最少3个参数,最多3个参数

   (SYSTEM::MACRO-CALL-ERROR SYSTEM::<MACRO-FORM>)

       如果参数个数不对,报错

   (LET* ((X (CADR SYSTEM::<MACRO-FORM>)) (Y (CADDR SYSTEM::<MACRO-FORM>)))

       列表中第一个元素是宏名,第2个元素就是参数X,第3个元素是参数Y

(BLOCK MOO `(FORMAT T "~A : ~A~%" ,X ,Y))))>

这就是宏的实现体,不用解释了

 

前面把宏的实现函数赋给变量moo-fun,调用它试一试,结果和macroexpand-1完全相同。

[9]> (funcall moo-fun '(moo 'asdf 'ar) nil)

(FORMAT T "~A : ~A~%" 'ASDF 'AR)

[10]>

 

       前一篇文章介绍了运行时修改函数的实现,同样地,也可以在运行时修改宏的实现,下载DTrace的源代码,看函数trace-macro的实现,方法是相似的。

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值