欢迎!请查看 关于 页面以了解更多信息。
(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),但这并不足够好。
内部和外部的函数表现相同 - 它们都接收到一个列表。
评估发生在调用之前(因此不是“函数”在执行评估,而是调用它的位置在执行评估)。
在这里,函数 func 和 helper 的参数是符号 expr。符号通过在当前词法环境中将该“名称”解析为值来进行评估,这里定义在 defmacro 参数中。它解析为列表 (+ 1 2)。该列表传递给函数。评估该列表需要评估参数两次!
func
helper
expr
(+ 1 2)
宏展开不是评估,并且参数不会被评估。