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只求值了一次,所以只会打印一次。