ELisp编程十三:宏二

为什么分两个步骤:先展开宏,再求值。

因为单单有一个宏定义(这里称macro body)是不能在编译时求值的,宏的参数还没呢。宏的参数必须要等到编译器看到宏调用代码的时候才能知道。因此将宏参数传递给宏定义,然后展开宏再求值,是唯一能行的方法。

很好理解,这里就像C++的一样。


反引号(Backquote)`

最简单的情况下,和‘功能相同,代表不要对一个list求值

     `(a list of (+ 2 3) elements)
          ⇒ (a list of (+ 2 3) elements)
     '(a list of (+ 2 3) elements)
          ⇒ (a list of (+ 2 3) elements)

上面两个表达式是等价的。

下面的宏

(defmacro inc (var)
        (list 'setq var (list '1+ var)))
用反引号的简化写法是:
(defmacro inc2 (var)
        `(setq ,var (1+ ,var)))


反引号的特殊在于如果在里面的list中使用,号,会告诉编译器如何展开该宏:

1.将,后面的求值,

2.用值来替换该处的原表达式

`(a list of ,(+ 2 3) elements)
          ⇒ (a list of 5 elements)

这里,(+2 3) 被求值成了5,5就作为一个元素加入到这个list中。


这种用法可以应用在定义宏的时候,请注意差别很大。

(defmacro t-becomes-nil (variable)
       `(if (eq ,variable t)
            (setq ,variable nil)))

(macroexpand '(t-becomes-nil foo))
这句宏调用展开后等价于:

(if (eq foo t) (setq foo nil))
如果将宏定义中的,去掉,等价于:

(if (eq varialbe t) (setq variable nil))
此处没有求值。


`后面的表达式里面可以用,@符号表示将一个list的值添加进来,比如:

(setq some-list '(2 3))
          ⇒ (2 3)
     `(1 ,@some-list 4 ,@some-list)
          ⇒ (1 2 3 4 2 3)

可读性大大加强,另一种可读性差的写法:

(cons 1 (append some-list '(4) some-list))
          ⇒ (1 2 3 4 2 3)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值