Clojure宏扩展如何工作?

时间:2019-06-02 13:09:56

标签: clojure

我正在通过“勇敢与真实的Clojure”学习Clojure。

在宏课程中,我正在尝试以下宏,

(defmacro report
  [to-try]
  `(let [result# ~to-try]
     (if result#
       (println (quote ~to-try) "was successful:" result#)
       (println (quote ~to-try) "was not successful:" result#))))

下面是我对宏和相应输出的几个实验。

1

(map #(report %) ['(= 1 2) '(= 1 1)])
; p1__26622# was successful: (= 1 2)
; p1__26622# was successful: (= 1 1)

2

map #(report %) ['false 'true])
; p1__26612# was not successful: false
; p1__26612# was successful: true

我的问题是

  • 为什么在前一种情况下,宏对两个值都打印为真?
  • 据我所知,第二个完全等同于前一个。但是为什么给出不同的结果呢?

1 个答案:

答案 0 :(得分:4)

  

为什么在前一种情况下,宏对两个值都打印为真?

您的report宏正在接收引用列表作为输入,而不是可以评估为true / false的表达式。任何列表都是真实的,即使它包含一个计算结果为false的表达式。这将为您带来预期的结果:

(report (= 1 2)) ;; evaluates to false
  

据我所知,第二个完全等于前一个。但是为什么给出不同的结果呢?

这并不完全等效,因为第一个示例正在检查列表,第二个示例正在检查引用的布尔值。您的第二个示例将'false评估为假,因为if对待它的方式是:

(if 'false 0 1) => 1