0

I am getting an error and do not know how to fix it. I have to calculate square root with approximation and it should stop on the 20th element.

  • Unable to resolve symbol: aprox in this context, compiling:(/home/jdoodle.clj:2:2)

Code:

(defn msqrt [n]
    (aprox  (n 1.0 1)))
(defn aprox [n prox part]
(if (= part 20)
    prox
(+ (/ n (* 2 (aprox n part (+ part 1)))) (/ (aprox n prox (+ part 1))2)))
)
(msqrt 9)
FatTommy
  • 177
  • 1
  • 1
  • 10
  • 3
    This will still fail after you make the suggested change. You're attempting to call `n` as a function in `msqrt`. Not sure what you're trying to do there. Do you mean just `(aprox n 1.0 1)`? – Carcigenicate Mar 18 '18 at 19:29
  • 1
    Very true --^^. My answer is only the direct answer to that error, not a complete fix for your code. – jmargolisvt Mar 18 '18 at 19:32
  • 1
    Just comment about the recursive code. It will be very slow. I suggest you try to use a tail-recursive solution. (defn newt ([n] (newt n 1.0 20)) ([n guess step] (if (zero? step) guess (recur n (/ (+ guess (/ n guess)) 2.0) (dec step))))) – miner49r Mar 23 '18 at 16:59

2 Answers2

1

In Clojure, the order you declare functions in matters. They don't get hoisted up like in Javascript. You can fix this by either:

  1. Moving your defn aprox above defn msqrt
  2. Adding declare aprox to the top of your file to make it available

https://clojuredocs.org/clojure.core/declare

jmargolisvt
  • 5,722
  • 4
  • 29
  • 46
0

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))) 
Thumbnail
  • 13,293
  • 2
  • 29
  • 37