0
は私が再発を使用するhttps://github.com/lspector/gp/blob/master/src/gp/evolvefn_zip.clj
からのコードのこの部分を書き換えるしようとしています:末尾再帰を正しく使うには?
(defn random-code [depth]
(if (or (zero? depth)
(zero? (rand-int 2)))
(random-terminal)
(let [f (random-function)]
(cons f (repeatedly (get function-table f)
#(random-code (dec depth)))))))
問題があり、私はそれを行うにはどのように絶対にないアイデアを持っていません。それはちょうど私がそれを解決しようとする方法を示すことですが、コードの作業部分ではありません
(defn random-code [depth]
(loop [d depth t 0 c []]
(if (or (zero? depth)
(zero? (rand-int 2)))
(if (= t 0)
(conj c random-terminal)
(recur depth (dec t) (conj c (random-terminal))))
(let [f (random-function)]
(if (= t 0)
(recur (dec depth) (function-table f) (conj c f))
(recur depth (dec t) (conj c f)))))))
、それだけで、ますます複雑になるだろう:私は考えることができる
唯一のことは、このようなものです。
clojureで通常の再帰を末尾の再帰に変換するより良い方法はありますか?ここで
はい、ソリューションはコードのように畳み込まれている可能性が高くなります。あなたがツリーではなく、シーケンスを構築する理由。シーケンスを構築する場合は、通常、アキュムレータパラメータを追加します。このパラメータは、コード内のconjを置き換えます。 すべての関数が2つのchildreenを持つノードである場合、それは機能しません、両方の子にaccを送信することはできません。 なぜテール再帰が必要ですか? DEPTHがJavaスタックより大きいツリーを生成する場合にのみ必要です。 Javaは1000フレームの深さのスタックを持つことに問題はありません。テール再帰はおそらくあなたのバージョンよりも遅くなるでしょう。 – mattias