clojure待解决问题?

1,https://stackoverflow.com/questions/56030237/variable-capture-with-macro-in-clojure 【已解决】

(defmacro t2macro [all-bindings body] (reduce (fn [acc [v binding]]
                                                 `(let [~v ~binding] ~acc))
                                                   `(do ~@body) all-bindings))
plans-client.mock> (t2macro [[a 1] [b 2]] (print (+ a b)))
3

宏展开:

(macroexpand-1  '(t2macro [[a 1] [b 2]] (print (+ a b))))
=> (clojure.core/let [b 2] (clojure.core/let [a 1] (do print (+ a b))))

这段宏展开代码该怎么理解?
匿名函数总共调用了几次?为什么只有一次println?
解答:这里涉及到reduce的逻辑reduce文档,reduce如果是(reduce f val coll)形式调用的话,
那么执行顺序如下:
f(val, coll第一个元素) =》 tmp
f(tmp, coll第二个元素) =》tmp
直至coll最后一个元素。
回到代码本身,(let [~v ~binding] ~acc))其实是执行了let绑定,并把acc原封不动的返回了,由于是被syntax quote处理过的,所以不会求值,所以reduce的f的第一个参数一直都是acc,直到最后返回的时候被求值,acc只求值了一次,所以只会打印一次。

posted @ 2022-10-18 20:44  堕落门徒  阅读(19)  评论(0编辑  收藏  举报