Summary of problems solved by the SICP exercise (1.46), sicp1.46
Exercise 1.46 requires us to write a process iterative-improve, which takes two procedures as the parameter, one parameter is used to check whether the guess is good enough, and the other parameter is used to improve the guess. Process iterative-improve should return another process, the returned process receives a parameter as the initial guess, and then continuously improves the guess until the result is good enough. The question also requires us to use iterative-improve to rewrite the sqrt process of 1.1.7 and the fixed-point process in Section 1.3.3.
As it involves higher-order functions, it is difficult to understand the entire question. However, this question, as the ending question of the first chapter, is indeed very suitable. It involves "process as a parameter" and "process as a return value". These two points are almost all of the higher-order functions. Of course, the most important thing is the soul of high-level functions-abstraction, which is the abstraction of general processes and the abstraction of abstract processes. Here we need to abstract sqrt and fixed-point into a general process.
To solve this problem, we need to go back and look at the sqrt process defined in section 1.1.7. The process code is as follows:
(define (sqrt-iter guess x)(if (good-enough? guess x)guess(sqrt-iter (improve guess x) x)))
If we abstract the common things in the sqrt process, there are three key things:
1. Current guess,
2. Check whether the result is good enough,
3. Improved speculation.
The organization of the above three key things is as follows:
If the current guess is good enough, the current guess will be returned. If it is not good enough, the guess will be improved by some means and the new guess will be judged again.
The possible situation is as follows:
(Define (my-proc judges the method of speculation to improve the current method of speculation) (if (the current guess is good enough) current prediction (my-proc judges the method of speculation and improves the method of speculation (improves the method of speculation ))))
The corresponding code is as follows:
(define (improve-guess-inner good-enough? improve current-guess) (if (good-enough? current-guess)current-guess(improve-guess-inner good-enough? improve (improve current-guess)))
The book also mentions that the method iterative-improve that we are required to do should return a process that accepts the initial guess as the unique parameter and then starts constantly improving the guess calculation.
So we can package the above code to get our iterative-improve process:
(define (iterative-improve good-enough? improve) (define (improve-guess-inner good-enough? improve current-guess) (if (good-enough? current-guess)current-guess(improve-guess-inner good-enough? improve (improve current-guess)))) (lambda (guess) (improve-guess-inner good-enough? improve guess)))
Note that it returns a lamda function.
Well, the above is the first half of the question. The second half requires us to use iterative-improve to rewrite the sqrt and fixed-point processes.
If the improve-guess-inner process is called directly, the new sqrt process can be written as follows:
(improve-guess-inner sqrt-good-enough? sqrt-improve 1.0)
However, our improve-guess-inner is an internal method and cannot be used directly. We need to use iterative-improve to call it. The call method is as follows:
((iterative-improve sqrt-good-enough? sqrt-improve) 1.0)
Among them, good-enough? The process is as follows:
(define (sqrt-good-enough? guess) (< (abs (- x (* guess guess))) small-number)
The sqrt-improve process is as follows:
(define (sqrt-improve cur-guess) (/ (+ (/ x cur-guess) cur-guess) 2))
Therefore, the overall implementation of the new sqrt process is as follows:
(define (new-sqrt x) (define (sqrt-good-enough? guess) (< (abs (- x (* guess guess))) small-number)) (define (sqrt-improve cur-guess) (/ (+ (/ x cur-guess) cur-guess) 2)) ((iterative-improve sqrt-good-enough? sqrt-improve) 1.0))
Let's take a look at the definition of the fixed-point Process in Section 1.3.3. The Code is as follows:
(define (fixed-point f first-guess) (define (close-enough? v1 v2) (< (abs (- v1 v2 )) tolerance)) (define (try guess) (newline) (display (+ 0.0 guess)) (let (( next (f guess))) (if (close-enough? guess next) (+ 0.0 next) (try next)))) (try first-guess))
This Code seems to be quite different from the sqrt program. However, if you carefully observe the fixed-point process, you can find that its key idea is the same as that of sqrt, it is to check whether the current guess is good enough. If it is good enough, it will return the current guess. If it is not good enough, it will improve the guess by some means and judge the new guess again...
The method for judging the guess is close-enough.
There is a problem, the previous good-enough? The method only accepts one parameter, while the close-enough method accepts two parameters to determine whether the two parameters are close enough.
To solve this problem, we need to examine the working principle of fixed-point. Among them, close-enough needs to determine whether guess and (f guess) are close enough, so we can re-define close-enough.
(define (fp-good-enough? cur-guess) (< (abs (- cur-guess (f cur-guess))) small-number))
It is used to compare whether cur-guess and (f cur-guess) are close enough. Note that this process must be defined where Process f is valid.
For the fixed-piont process, the method for improving the guess is f itself. If you do not understand this, you need to go back to Section 1.3.3 to discuss the fixed-point process.
Therefore, the new fixed-point process can be written as follows:
(improve-guess-inner fp-good-enough? f guess)
Because improve-guess-inner cannot be called directly, the code for calling iterative-improve is as follows:
((iterative-improve fp-good-enough? f) first-guess)
The final new-fiexed-point process is as follows:
(define (new-fixed-point f first-guess) (define (fp-good-enough? cur-guess) (< (abs (- cur-guess (f cur-guess))) small-number)) ((iterative-improve fp-good-enough? f) first-guess))
The last one is to define the value of small-number:
(define small-number 0.000001)
The above is the summary of the problem solving of the SICP exercise 1.46. There are several key points, one is "process as a parameter", the other is "process as a return value", and the other is the image of the general process, abstract The general process to generate a more general process.
Finally, there is a hidden knowledge point, that is, the scope of the variables in the lambda function. This requires special attention when writing code.