clojure循环看到价值观

时间:2016-08-07 20:59:42

标签: loops debugging clojure

使用reduce时,reductions函数可以查看连续减少的列表。是否有类似于在Clojure中调试loop的内容?

2 个答案:

答案 0 :(得分:2)

loop / recurreductions更为必要;你可能只是自己将自己的日志记录插入到循环体中,或者维护一个原子的值列表,或者在功能上,最好将一个(其他)累加器引入循环参数。

答案 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和{{替换了所有内部looprecur s 1}},而loop+将此隐式变量添加到recur+调用(带recur+的部分,recurval-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]]}