質問

Most reference to iterate are for operators, and all the applications on functions are so confusing that I still don't get how to use iterate in my code, and what partial is.

I am doing a programming homework, trying to use Newton's method to get square root for a number n. That is, with guess as the initial approximation, keep computing new approximations by computing the average of the approximation and n/approximation. Continue until the difference between the two most recent approximations is less than epsilon.

I am trying to do the approximation part first, I believe that is something I need to use iterate and partial. And later the epsilon is something I need to use "take"?

Here is the code I have for approximation without the epsilon:

(defn sqrt [n guess]
  (iterate (partial sqrt n) (/ (+ n (/ n guess)) 2)))

This code does not work properly though, when I enter (sqrt 2 2), it gives me (3/2 user=> ClassCastException clojure.lang.Cons cannot be cast to java.lang.Number clojure.lang.Numbers.divide (Numbers.java:155).

I guess this is the part I need to iterate over and over again? Could someone please give me some hints? Again, this is a homework problem, so please do not provide me direct solution to the entire problem, I need some ideas and explanations that I can learn from.

役に立ちましたか?

解決

partial takes a function and at least one parameter for that function and returns a new function that expects the rest of the parameters.

(def take-five (partial take 5))
(take-five [1 2 3 4 5 6 7 8 9 10])
;=> (1 2 3 4 5)

iterate generates an infinite sequence by taking two parameters: a function and a seed value. The seed value is used as the first element in the generated list and the second is computed by applying the function to the seed, the second value is used as the input for the function to get the third value and so on.

(take-five (iterate inc 0))
;=> (0 1 2 3 4)

ClojureDocs offers good documentation on both functions: http://clojuredocs.org/clojure_core/clojure.core/iterate and http://clojuredocs.org/clojure_core/clojure.core/partial.

他のヒント

So, @ponzao explained quite well what iterate and partial do, and @yonki made the point that you don't really need it. If you like to explore some more seq functions it's probably a good idea to try it anyways (although the overhead from lazy sequences might result in a somewhat not ideal performance).

Hints:

  • (iterate #(sqrt n %) initial-approximation) will give you a seq of approximations.
  • you can use partition to create pairs of subsequent approximations.
  • discard everything not fulfilling the epsilon condition using drop-while
  • get result.

It's probably quite rewarding to solve this using sequences since you get in contact with a lot of useful seq functions.

Note: There is a full solution somewhere in the edit history of this answer. Sorry for that, didn't fully get the "homework" part.

I think you're missing the point. You don't need iterate neither partial too.

If you need to execute some computation till condition is fulfilled you can use easy to understand loop/recur instruction. loop/recur can be understood as: do some computation, check if condition is fulfilled, if yes return computed value, if not repeat computation.

Since you don't want entire solution, only an advice where to go, have a proper look on loop/recur and everything gonna be all right.

@noisesmith made good point. reduce is not for computing till condition is fullfiled, but may be useful when performing some computation with limited number of steps.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top