Wie kann man in Clojure die Nicht-Tail-Rekursion mit der synchronisierten Memoisierung und dem begrenzten Stack-Verbrauch (also kein Risiko eines Stack-Überlaufs) kombinieren? Mit synchronisierter Memoisierung meine ich, dass der Memo/Cache gleichzeitig und effizient zwischen Threads geteilt werden muss.Wie kombiniere ich nicht-Tail-Rekursion + effektive und synchronisierte Memoization + Bounded Stack-Verbrauch in Clojure?
Mein spezieller Fall ist wie folgt:
; g() is non recursive
; i is an integer
; h is a hash with int keywords and vector of ints values
; w is a hash with int keywords and int values
(defn g [i h w]
(filter
#(-> (w %)
(= i))
(h i)))
; f is recursive, recurses non-trivially (non-tail, multiple times)
; TODO: be memoizable (ideally in a synchronized way, for parallelism)
; TODO: pose no risk stack overflow
(defn f [i h w]
(if (nil? (h i))
0
(let [part_sum
(map ; will change this map to pmap or pvmap
#(f % h w)
(g i h))]
(-> (reduce + part_sum)
(/ 2)
(+ 1)))))
; trivial, shown for completeness
(defn ff [i h w]
(-> (f i h w)
(- 1)
(* 2)
(max 0)))
In Bezug auf memoization zu kümmern: [ 'memoize'] (https: //clojuredocs.org/clojure.core/memoize) aus Kern lib [Verwendungen] (https://github.com/clojure/clojure/blob/a752736c1a14dce31e2f1cc30adde741328b4b12/src/clj/clojure/core.clj#L6078) -Atom unter der Kapuze, so sollte es Gewinde sicher sein, glaube ich – OlegTheCat
In Bezug auf die Vermeidung von Stack-Überlauf: Das ist allgemeine Frage, die nicht clojure spezifisch ist, würde ich sagen. [Hier] (http://programmers.stackexchange.com/questions/194646/what-methods-are-there-to-avoid-a-stack-overflow-in-a-recursive-algorithm) finden Sie einige allgemeine Ansätze das Problem zu lösen. – OlegTheCat