Programming Clojure学习笔记——宏

7.3 使宏简单化
Clojure为宏作者提供的支持
形式                描述
foo#                在语法上被引号引起的区域内,创建一个以foo为前缀的唯一名称
(gensym prefix?)            以可选的前缀prefix创建唯一名称
(macroexpand form)        使用macroexpand-1递归展开form,直到没有宏为止
(macroexpand-1 form)        显示form如何展开
(list-frag? ~@form list-frag?)    拼接引用: 在语法引用中将引用列表拼接到模板中
`form                语法引用(Syntax quote): 引用形式, 允许form内部结束引用从而实现模板功能.form中的符号在解析时不会出现无意的符号捕获
~form                引用结束(Unquote): 在语法引用中用来替代结束引用的值.

说明:符号捕获指的是在宏展开时,如果允许使用非限制的符号,如果这些符号已经绑定其他的值,宏将捕获这些符号,然后将它们绑定到其他值上,从而出现怪诞的结果。

语法引用(Syntax Quote), 结束引用(Unquote)和拼接结束引用(Splicing Unquote)
语法引用字符(`)作用类似普通引号,但是在语法引用的列表中,结束引用字符(~)可以多次结束引用,它们一起实现模板功能,如下:
user=> (defmacro chain [x form]
     `(. ~x ~form))
对于单个方法调用可以正确生成:
user=> (macroexpand '(chain arm getHand))
(. arm getHand)
但是对于有多个参数的变体chain,不能正确展开:
user=> (defmacro chain
([x form] `(. ~x ~form))
([x form & more] `(chain (. ~x ~form) ~more)))
#'user/chain
user=> (macroexpand '(chain are getHand getFinger))
(. (. are getHand) (getFinger))
说明:由于chain的最后一个参数more是一个列表,因此代入模板时被括号包围。

通过拼接引用(~@)宏可以正确的实现上述功能:
user=> (defmacro chain
([x form] `(. ~x ~form))
([x form & more] `(chain (. ~x ~form) ~@more)))
user=> (macroexpand '(chain arm getHand getFinger))
(. (. arm getHand) getFinger)

在宏中创建命名
Clojure提供一个读者形式创建唯一的局部名称。在语法引用形式中,可以在非限定名称后添加一个井号(#),Clojure将自动创建一个符号:由非限定名称+下划线+唯一ID组成。如:
(defmacro bench [expr]
    `(let [start# (System/nanoTime)
    result# ~expr]
    {:result result# :elapsed (- (System/nanoTime) start#)}))
user=> (bench (str "a" "b"))
{:result "ab", :elapsed 88822}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值