2014-11-16 8 views
6

In clojure v1.6.0 wirft, dieser Code ausgeführt wird nur immer und verbraucht 100% eines Kern:Warum dieser Code nicht Stackoverflow Ausnahme

(defn average [x y] (/ (+ x y) 2)) 

(defn improve [guess x] 
    (average guess (/ x guess))) 

(defn sqrt-iter [guess x] 
    (sqrt-iter (improve guess x) x)) 

(sqrt-iter 1 4) 

Ich würde erwarten, dass es eine StackOverflowError sofort zu werfen, aber es nicht.

Jede Erklärung, warum es passiert?

Antwort

8

Weil 1 lang ist. Der Code beginnt mit der Berechnung extrem langer Rationalwerte und verlangsamt sich nach einigen Iterationen auf einen Crawlvorgang. Wenn Sie es mit 1.0 und 4 ausführen, bläst es den Stack sehr schnell nach ein paar tausend Anrufe (kann je nach Ihren jvm-Parametern variieren).

+1

Um zu überlaufen, müssen nur einige tausend Anrufe ausgeführt werden. Ist es wirklich lang arithmetisch * so langsam *, dass es 10k Divisionen und Summen nicht schnell berechnen kann? – zerkms

+4

Es ist nicht lange Arithmetik. Es ist ein Verhältnis, das BigIntegers im Nenner und Zähler enthält. BigIntegers wird beliebig lange wachsen. Siehe https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Ratio.java –