Recursion 不要在递归中重复我自己
我使用Recursion 不要在递归中重复我自己,recursion,clojure,Recursion,Clojure,我使用循环递归和一些相当复杂的逻辑进行递归。事实证明,我应该在两个分支中做相同的事情,这两个分支都应该导致递归。我不相信我能用一个函数把它抽象出来,因为recur的局限性,所以我怎样才能做到这一点,并且没有重复的代码。我必须使用宏吗 代码在下面,重复代码在这里用重复代码突出显示 (defn overlapping-sampler [n-samples] (let [...] (loop [samples [] cache (zipmap boxes []) n-samples n-s
循环
递归
和一些相当复杂的逻辑进行递归。事实证明,我应该在两个分支中做相同的事情,这两个分支都应该导致递归。我不相信我能用一个函数把它抽象出来,因为recur的局限性,所以我怎样才能做到这一点,并且没有重复的代码。我必须使用宏吗
代码在下面,重复代码在这里用重复代码突出显示
(defn overlapping-sampler [n-samples]
(let [...]
(loop [samples [] cache (zipmap boxes []) n-samples n-samples]
(cond
(zero? n-samples)
samples
:else
(let [box (categorical boxes volumes)
cache-item (peek (cache box))]
(if (nil? cache-item)
; REPEATED CODE HERE
(let [sample (interval-sample (:internals box))
all-boxes (map #(apply (:formula %) sample) boxes)
pos-dominant (max-pred-index true? all-boxes)
pos-box (max-pred-index #(= box %) boxes)]
(if (= pos-dominant pos-box)
(recur (conj samples sample) cache (dec n-samples))
(recur samples
(update-in cache [(nth boxes pos-dominant)]
#(conj % {:from box :sample sample}))
n-samples)))
; Otherwise with prob p=ratio of overlapping region/box, take sample
(if (flip (/ (volume (overlap box (:from cache-item))) (volume box)))
(recur (conj samples (:sample cache-item)) ; I should take the sample
(update-in cache [box]
#(pop %))
(dec n-samples))
(let [sample (gen-until #(interval-sample (:internals box))
#(and (apply (:formula box) %)
(not (apply (:formula (:from cache-item)) %))))
;REPEATED CODE HERE
all-boxes (map #(apply (:formula %) sample) boxes)
pos-dominant (max-pred-index true? all-boxes)
pos-box (max-pred-index #(= box %) boxes)]
(if (= pos-dominant pos-box)
(recur (conj samples sample) cache (dec n-samples))
(recur samples
(update-in cache [(nth boxes pos-dominant)]
#(conj % {:from box :sample sample}))
n-samples))))))))))
使用本地函数:
(defn overlapping-sampler [n-samples]
(let [fun (fn [sample samples]
(let [all-boxes (map #(apply (:formula %) sample) boxes)
pos-dominant (max-pred-index true? all-boxes)
pos-box (max-pred-index #(= box %) boxes)]
(if (= pos-dominant pos-box)
[(conj samples sample) cache (dec n-samples)]
[samples
(update-in cache [(nth boxes pos-dominant)]
#(conj % {:from box :sample sample}))
n-samples])))]
(loop [[samples cache n-samples] [[] (zipmap boxes []) n-samples]]
(cond
(zero? n-samples)
samples
:else
(let [box (categorical boxes volumes)
cache-item (peek (cache box))]
(if (nil? cache-item)
; REPEATED CODE HERE
(let [sample (interval-sample (:internals box))]
(recur (fun sample) samples))
; Otherwise with prob p=ratio of overlapping region/box, take sample
(if (flip (/ (volume (overlap box (:from cache-item))) (volume box)))
(recur [(conj samples (:sample cache-item)) ; I should take the sample
(update-in cache [box]
#(pop %))
(dec n-samples)])
(let [sample (gen-until #(interval-sample (:internals box))
#(and (apply (:formula box) %)
(not (apply (:formula (:from cache-item)) %))))]
(recur (fun sample) samples)))))))))
也许改写成
(let [cache-item ...]
(if (and (nil? cache-item) (flip ...))
(recur ...)
(let [sample (if (nil? cache-item)
(... calculate sample ... )
(... use cache-item ... ))
; REPEATED CODE HERE
...]
...)))
这将在if
的“else”分支中测试(nil?缓存项)
两次。您可以引入缓存命中?
本地来存储(nil?缓存项)
的值,以避免重复键入nil?
调用;但是,不是出于性能原因,因为实际上应该没有区别