深入了解lisp(clojure)-宏

本文由larrylgq编写,转载请注明出处:http://blog.csdn.net/larrylgq/article/details/7395261

作者:吕桂强

邮箱:larry.lv.word@gmail.com



lisp使用特殊操作符来扩展语法,但是在lisp中特殊操作符的数量是固定的,为了解决这个问题lisp引入了宏,宏并不直接做事,而是生成实际的业务代码。

宏的求值过程:接收S-表达式为参数,返回一个lisp展开式(ecpansion),对该展开式求值。

编译过程:在clojure中使用compile编译源文件的时候,将文件中所有宏递归展开成展开式,此时代码中只有函数调用形式和特殊形式。将展开后的代码编译成FASL文件,使用LOAD函数加载时会执行这些编译过的代码。

由于宏不会被直接求值的特性,所以我们定义的宏可以不是标准格式的lisp,每个宏都可以定义自己的语法。

相较于使用核心加上标准库的方式定义的语言,lisp可以通过宏来定义新的语法,并将它放在标准库里,而不是硬编码在语言核心。

当然你也可以将自己会大量复用的代码抽象成宏来使代码更简洁。

 

宏的结构:名字+形参列表+可选文档字符串+声明+lisp表达式体

一个简单的例子,使用宏实现

(defmacro while
  "Repeatedly executes body while test expression is true. Presumes
  some side-effect will cause test to become false/nil. Returns nil"
  {:added "1.0"}
  [test & body]
  `(loop []
     (when ~test
       ~@body
       (recur))))


当我们这样调用的时候:

user=> (def a (atom 10))                                
#'user/a
user=> (while (pos? @a) (do (println @a) (swap! a dec)))

将会在编译器产生如下代码:

(defn while [(pos? a) (do (println @a) (swap! a dec))]

(loop [] (

 (when (pos? a)

  (do (println @a) (swap! a dec))

  (recur)

)

)))

符号使用:

反引号 :防止宏体内的表达式被evaluate。

波浪号:使用在在反引号里面,它的值会被替换。

~@: 替换某个具体元素。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值