请在 2024 年 Clojure 状况调查! 分享您的想法。

欢迎!请查看 关于 页面以了解更多信息。

0
(defmacro test [expr]
  (letfn [(helper [expr]
            (println expr)
            (rest expr))]
    (func expr)
    (helper expr)))

(defn func [x]
 (println x))

(macroexpand '(test (+ 1 2)))

;;the evaluator prints:
;;(+ 1 2)
;;(+ 1 2)
;;(1 2)

这非常不符合直觉,因为内部定义的函数(辅助函数)和外部函数(func)在执行 (+ 1 2) 操作时表现相似,都没有评估参数。关于这个问题在 stackoverflow.com 上有回答(https://stackoverflow.com/questions/54394977/evaluation-of-arguments-in-function-called-by-macro),但这并不足够好。

1 答案

+3

已选择
 
最佳答案

内部和外部的函数表现相同 - 它们都接收到一个列表。

评估发生在调用之前(因此不是“函数”在执行评估,而是调用它的位置在执行评估)。

在这里,函数 funchelper 的参数是符号 expr。符号通过在当前词法环境中将该“名称”解析为值来进行评估,这里定义在 defmacro 参数中。它解析为列表 (+ 1 2)。该列表传递给函数。评估该列表需要评估参数两次!

宏展开不是评估,并且参数不会被评估。

by
非常感谢!
...