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)。该列表被传递给函数。评估该列表需要评估参数两次!

宏展开不是评估,参数也不被评估。

非常感谢!
...