【发布时间】:2013-06-02 06:30:14
【问题描述】:
Clojure 是我第一次涉足 lisp 世界。我决定尝试一个简单的递归函数,它将一个数字提高到整数幂。很简单。
(defmulti pow #(compare %2 0))
(defmethod pow 0 [a n] 1)
(defmethod pow 1 [a n] (* a (pow a (dec n))))
(defmethod pow -1 [a n] (/ 1 (pow a (* -1 n))))
如果你只传递整数幂,它就可以正常工作。但是当我使用它来提升到足够大的功率时,我会出现堆栈溢出(可以预见)。
问题是,我怎样才能知道函数在死前的递归深度?了解我可以递归的深度的一种方法是通过执行以下操作:
(defn max-depth [n]
(try
(max-depth (inc n))
(catch StackOverflowError err (do
(printf "%s at %d\n" err n)
n)
)))
(Clojure 是我第一次尝试 lisp,所以我真的不知道如何让代码看起来可读。)这段代码只是无限递归,直到它溢出堆栈,然后返回它之前发生的递归次数炸毁了。这只能让我大致了解我可以走多远……这种方法存在很多问题。
我可以做的另一件事是捕获异常并尝试自己展开堆栈...但是我真的看不到从异常中获取我想要的信息的方法。查看http://docs.oracle.com/javase/6/docs/api/java/lang/StackOverflowError.html 的 StackOverflowError 的 javadoc,我看到了一些看起来很有希望的方法,但据我所知,没有任何结果。
我尝试运行 (count (.getStackTrace error)) ,其中错误是我捕获的堆栈溢出,但结果仅为 1024,因为“在某些情况下,可能会省略堆栈帧”。所以这没有用。
我唯一能想到的另一件事是在连续更大的指数上运行 pow,但这并不能真正告诉我调用堆栈有多深,它只告诉我可以提高到多大的指数(由于函数调用了其他函数,所以两个答案不一样)。
我也不知道在 java 中有什么方法可以做到这一点,但如果有的话,那么这个答案也可能会有所帮助。
有什么想法吗? 谢谢, --斯科特
【问题讨论】:
标签: recursion clojure stack-overflow