LISP 8.8 编写宏中宏

宏的作用是将常见的句法模式抽象掉,而反复出现在宏编写的特定模式同样也可受益于其抽象能力。

最后的几个do-primes函数中,都是以let形式确保子形式仅被求值一次的,引入了一些变量用来保存宏展开过程中用到的生成符号。

这也是一个常见模式,同样的也可以使用一个宏来将它抽象掉。


;;;编写宏中宏
(defmacro with-gensyms ((&rest names) &body body)
  `(let ,(loop for n in names collect `(,n (gensym)))
     ,@body))


(defmacro do-primes-4 ( (var start end) &body body)
  (with-gensyms (ending-value)
   `(do ((,var(next-prime ,start) (next-prime(1+ ,var)))
	  (,ending-value ,end))
	 ((> ,var ,ending-value))
       ,@body)))


每个绑定形式由一个含有with-gensyms中的一个给定名字和字面代码(gensym)的列表所构成。

你可以通过将name替换成一个符号的列表,从而测试LOOP表达式生成的代码:

CL-USER> (loop for n in '(hello world) collect `(,n (gensym)))
((HELLO (GENSYM)) (WORLD (GENSYM)))



下面的两份段话值得分析:

当编译关于do-primes的defmacro时,with-gensyms形式就被展开并被编译。

这样,do-primes的编译版本就已经跟你手写外层的let时一样。


当编译一个使用了do-primes的函数时,由with-gensyms生成的代码将会运行用来生成do-primes的展开式,

但with-gensyms宏本身在编译一个do-primes形式时并不会被用到,因为在do-primes被编译时,with-gensyms已经被展开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值