Clojure宏扩展是如何工作的?

Clojure宏扩展是如何工作的?,clojure,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#)))) 下面是我

我在学习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. 2. 我的问题是

为什么在前一种情况下,宏打印的两个值都为true? 依我的理解,第二个与前一个完全相同。但为什么它会给出不同的结果呢? 为什么在前一种情况下,宏打印的两个值都为true

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

(report (= 1 2)) ;; evaluates to false
依我的理解,第二个与前一个完全相同。但为什么它会给出不同的结果呢

这并不完全相同,因为第一个例子是检查列表,第二个是检查引用的布尔值。您的第二个示例将“false”评估为false,因为if就是这样处理的:

(if 'false 0 1) => 1
为什么在前一种情况下,宏打印的两个值都为true

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

(report (= 1 2)) ;; evaluates to false
依我的理解,第二个与前一个完全相同。但为什么它会给出不同的结果呢

这并不完全相同,因为第一个例子是检查列表,第二个是检查引用的布尔值。您的第二个示例将“false”评估为false,因为if就是这样处理的:

(if 'false 0 1) => 1
您可以使用macroexpand-1查看使用宏时代码转换为什么。您可以使用macroexpand-1查看使用宏时代码转换为什么。false生成false,就像“1生成1一样,因为false是一个文本,而不是if处理它的方式。”false生成false,就像“1生成1,因为false是一个字面意思,而不是因为if是这样对待它的。