Clojure:简单的阶乘导致堆栈溢出 [英] Clojure: Simple factorial causes stack overflow
问题描述
我做错了什么?简单递归几千个调用深度抛出一个 StackOverflowError
。
What am I doing wrong? Simple recursion a few thousand calls deep throws a StackOverflowError
.
如果Clojure递归的限制如此低,我可以依靠它吗?
If the limit of Clojure recursions is so low, how can I rely on it?
(defn fact[x]
(if (<= x 1) 1 (* x (fact (- x 1)) )))
user=> (fact 2)
2
user=> (fact 4)
24
user=> (fact 4000)
java.lang.StackOverflowError (NO_SOURCE_FILE:0)
推荐答案
堆栈大小,我明白,取决于你使用的JVM以及平台。如果使用Sun JVM,可以使用 -Xss
和 -XThreadStackSize
参数来设置堆栈大小。
The stack size, I understand, depends on the JVM you are using as well as the platform. If you are using the Sun JVM, you can use the -Xss
and -XThreadStackSize
parameters to set the stack size.
在Clojure中,递归的首选方法是使用 loop
/ recur
:
The preferred way to do recursion in Clojure though is to use loop
/recur
:
(defn fact [x]
(loop [n x f 1]
(if (= n 1)
f
(recur (dec n) (* f n)))))
Clojure将为此进行尾调用优化;确保你不会遇到 StackOverflowError
。
Clojure will do tail-call optimization for this; that ensures that you’ll never run into StackOverflowError
s.
编辑:为了记录,这里是一个Clojure函数返回所有阶乘的延迟序列:
For the record, here is a Clojure function that returns a lazy sequence of all the factorials:
(defn factorials []
(letfn [(factorial-seq [n fact]
(lazy-seq
(cons fact (factorial-seq (inc n) (* (inc n) fact)))))]
(factorial-seq 1 1)))
(take 5 (factorials)) ; will return (1 2 6 24 120)
这篇关于Clojure:简单的阶乘导致堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!