The corrected answer compiles, but, but does not do what it ought to. The first reference to part
in the aprox
function ought to be to prox
:
(defn aprox [n prox part]
(if (= part 20)
prox
(+
(/ n (* 2 (aprox n prox (inc part))))
(/ (aprox n prox (inc part)) 2))))
I've taken the chance to improve layout and brevity.
It works:
> (msqrt 9)
=> 3.0
But it makes the same recursive call twice. It only need do so once:
(defn aprox [n prox part]
(if (= part 20)
prox
(let [deeper-prox (aprox n prox (inc part))]
(+
(/ n (* 2 deeper-prox))
(/ deeper-prox 2)))))
There are now about twenty recursive calls instead of about a million (2^20).
And we can see how this works. In the recursive call,
- the
part
argument counts up to 20
, creating a call stack twenty
deep;
- the
prox
argument uses the recursion to generate and
return an improved estimate of itself;
- the
n
argument is passed on unaltered.
We can get the same effect by repeating the improvement process twenty times and folding it into the msqrt
function:
(defn msqrt [n]
(loop [prox 1.0, part 20]
(if (pos? part)
(recur (+ (/ n (* 2 prox)) (/ prox 2)) (dec part))
prox)))