【发布时间】:2017-02-21 23:09:26
【问题描述】:
我正在尝试从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 个子节点的节点,它不起作用,您不能将 acc 发送到两个子节点。为什么要尾递归?只有当你想生成一个深度大于 Java 堆栈的树时,你才需要这个。 Java 拥有 1000 帧深的堆栈没有问题。尾递归可能会比你的版本慢。
标签: recursion clojure tail-recursion