蹦床如何在Clojure中使用多种方法

时间:2015-05-19 19:49:48

标签: recursion clojure

我试图理解如何使用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)

1 个答案:

答案 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