使用reduce
时,reductions
函数可以查看连续减少的列表。是否有类似于在Clojure中调试loop
的内容?
答案 0 :(得分:2)
loop
/ recur
比reductions
更为必要;你可能只是自己将自己的日志记录插入到循环体中,或者维护一个原子的值列表,或者在功能上,最好将一个(其他)累加器引入循环参数。
答案 1 :(得分:2)
@progo是对的,你总是可以添加另一个累加器,但是如果你真的不想每次都这样做,你可以让一些实用程序宏为你做这个,同时在语义上等于默认值{{1 (我想的是loop/recur
对(后者将被隐式使用):
loop+/recur+
正如您所看到的,(defmacro recur+ [& args]
(let [names (repeatedly (count args) gensym)]
`(let ~(vec (interleave names args))
(recur ~@names (conj ~'&loop-history [~@names])))))
(defmacro loop+ [bindings & body]
(let [val-names (repeatedly (/ (count bindings) 2) gensym)
vals (take-nth 2 (rest bindings))
binding-lefts (take-nth 2 bindings)]
`(let [~@(interleave val-names vals)]
(loop [~@(interleave binding-lefts val-names)
~'&loop-history [~(vec val-names)]]
~@(clojure.walk/postwalk-replace
{'recur 'recur+
'loop 'loop+}
body)))))
引入了隐式值loop+
,并用&loop-history
和{{替换了所有内部loop
和recur
s 1}},而loop+
将此隐式变量添加到recur+
调用(带recur+
的部分,recur
和val-names
对于避免双重评估至关重要传递给vals
)的表格。
所以,想象你有这样的循环:
binging-lefts
使用新循环只调用循环+而不是循环:
loop+
它扩展为以下内容:
user> (loop [a 1 b 2]
(if (<= b 10)
(recur a (inc b))
(str a " " b)))
"1 11"
现在user> (loop+ [a 1 b 2]
(if (<= b 10)
(recur a (inc b))
(str a " " b)))
"1 11"
完全可以在循环+内的任何地方访问:
(let*
[G__20054 1 G__20055 2]
(loop*
[a G__20054 b G__20055 &loop-history [[G__20054 G__20055]]]
(if (<= b 10)
(let*
[G__20056 a G__20057 (inc b)]
(recur
G__20056
G__20057
(conj &loop-history [G__20056 G__20057])))
(str a " " b))))
注意,它还为内部循环引入了&loop-history
,而无需更改源代码:
user> (loop+ [a 1 b 2]
(if (<= b 10)
(do
(println "history length: " (count &loop-history)
"last item: " (last &loop-history))
(recur a (inc b)))
{:result (str a " " b)
:history &loop-history}))
;; history length: 1 last item: [1 2]
;; history length: 2 last item: [1 3]
;; history length: 3 last item: [1 4]
;; history length: 4 last item: [1 5]
;; history length: 5 last item: [1 6]
;; history length: 6 last item: [1 7]
;; history length: 7 last item: [1 8]
;; history length: 8 last item: [1 9]
;; history length: 9 last item: [1 10]
;; {:result "1 11", :history [[1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [1 8] [1 9] [1 10] [1 11]]}