我试图理解如何使用trampoline
来支持尾递归的相互递归。但是,当下面的例子都编译相同的结果时,我会丢失。我相信每个defmethod
都必须返回一个函数,如下面的例2所示。但事实显然并非如此,因为示例1的效果一样好。那么两个实现下面的尾递归和相同的性能或它们之间有什么区别?
示例1:
(defmulti jump :beff)
(defmethod jump 1 [{:keys [beff]}]
(print beff)
(jump {:beff (inc beff)}))
(defmethod jump 2 [{:keys [beff]}]
(print beff)
(jump {:beff (inc beff)}))
(defmethod jump :default [{:keys [beff]}]
(print beff))
(def v {:beff 1})
(trampoline jump v)
示例2:
(defmulti jump :beff)
(defmethod jump 1 [{:keys [beff]}]
(print beff)
#(jump {:beff (inc beff)}))
(defmethod jump 2 [{:keys [beff]}]
(print beff)
#(jump {:beff (inc beff)}))
(defmethod jump :default [{:keys [beff]}]
#(print beff))
(def v {:beff 1})
(trampoline jump v)
答案 0 :(得分:3)
示例1错误,示例2正确。
第一个只能起作用,因为它只能重复两次并且不会使堆叠爆炸。对trampoline的调用什么都不做,因为函数永远不会返回一个函数,所以trampoline函数只返回它返回的值。
它的工作方式与此相同:
user> (trampoline (fn example
([] (example 4))
([x] (if (pos? x) (do (println x) (example (dec x)))))))
4
3
2
1
nil
在这种情况下,trampoline对函数进行初始调用,然后检查返回的值是否为函数。由于结果是数字42,它只是返回它。在示例1中,trampoline进行第一次调用,该调用在其自身内部一直重复并返回一个不是函数的值。蹦床然后返回这个值而没有"弹跳"一点都不这是另一个以同样的方式做错的例子:
CoreData