欢迎!请参阅关于页面以了解更多关于它的工作方式的信息。
(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)
宏展开不是评估,参数也不被评估。