**Study Notes for the tool (1.3.2 ~ 1.3.3)**

Zhou yinhui

**1. Lambda**

At the beginning of 1.3.2, it may cause a slight misunderstanding: I think it is for some convenience of expression, and then introduce the concept of Lambda in Scheme. This is not correct. In fact, Lambda is the mathematical basis of functional programming languages. It is the foundation and first appeared before other syntax forms. I personally feel that the above misunderstanding is reasonable in the Lambda expression of the imperative Language C #, because I always think that Lambda in C # Is a syntactic sugar coat introduced for a convenient expression, after all, it is not a functional language.

- "Alpha conversion" of lambda expressions"

We know that F (x) = ax + B is equivalent to F (y) = ay + B, we just replaced the variable x in the previous function expression with y. "Alpha conversion" describes this "Replacement" operation, which does not affect the original expression intent, for example (lambda (x) (+ (* a x) B )) it can be converted to (lambda (y) (+ (* a y) B) through alpha conversion )).
- "Beta simplification" of lambda expressions"

When a function is called, the formal parameters in the function are replaced with actual parameters, for example, F (2) = a * 2 + B, similarly, if a lambda expression (lambda (x) (+ (* a x) B) is applied to 2, it is reduced to (+ (* a 2) B)
- "Currying" of lambda expressions"

I don't know how to translate this operation. It refers to converting the form of lambda expressions from m parameters into forms with n parameters (where m, n is a positive integer, m> n)

For example, in our impression, suppose we need to define the sum operation of two numbers as follows: (define (add a B) (+ a B )), this requires two parameters for the add method, such as (add 2 3). What should we do if we only allow add to include one parameter? We should use the Currying technique to compile the following code:

(Define (add)

(Lambda (B) (+ a B )))

After that, you only need to input one parameter to call the add method, for example (add 2) 3)

Similarly, for lambda expressions with two parameters (lambda (x y) (+ x y) 2 3) it can be converted into a combination of two lambda expressions with one parameter (lambda (x) (lambda (y) (+ x y) 3 )) 2 ).

In fact, in the formal definition of the lambda expression in the "lambda computing" invented by Qiu Qi, the lambda expression itself contains only one parameter, currying is required for lambda computing with multiple parameters. Of course, for general programmers, we can still write lambda expressions with multiple parameters without worrying too much, because the interpreter will help us do a lot of work, it does not mean that learning currying has no practical significance. An obvious example is "exercise 1.33" in section 1.3.1 ", for more information, see "learning notes 1.3.1 ".
- Lambda count

If you ask a child, what is the value of 1 + 2? He may snap his finger and tell you 3. The "Finger breaking" Here is the key. In the opinion of the child, this is a computation process and a strict proof process. After studying mathematics for so many years, it is difficult to say that 1 + 2 is equal to 3 in the face of the same problem, except finger breaking.

However, Qiu Qi invented a counting method that makes it easy for you to launch 1 + 2, which is indeed 3.

To understand Qiu odd, we have to make the following assumptions (the following assumptions are my personal understanding, and I don't know whether there is any mathematical basis, at least it can help us understand Qiu ODD ):

If the following conditions are met, we will say that we have invented the natural number method.

1) define a successor function, which can express the meaning of "A natural number is either 0 or a natural number plus 1 ".

2) define a set of functions that can express "add", "Subtract", "Multiply", and "divide" (or more operations) respectively ).

3) prove that the natural numbers produced by the successor functions can be used for these operations.

Assume that the number n is represented by a lambda expression (lambda (s z) (s ^ n z), where s ^ n does not represent the n power of s, but (s ^ n z) to form a whole, the function s is applied n times on z. (s ^ n z) is equivalent to (s... (S z) a total of n times. So,

(Lambda (s z) indicates 0

(Lambda (s z) represents 1

(Lambda (s z) represents 2

And so on.

Using the above rules, we can generate the one, two, and three natural numbers:

(Define one (lambda (s z )))

(Define two (lambda (s z ))))

(Define three (lambda (s z )))))

Now let's assume that the add operation is defined as follows:

(Define add (lambda (s z x y) (x s (y s z ))))Let's take a look at how (add one two) gets three:

; Add operation definition, note that here is four parameters

(Define add (lambda (s z x y) (x s (y s z ))))

*; Use Currying to reduce four parameters to two*

(Define add (lambda (x y) (lambda (s z) (x s (y s z )))))

*; 1 and 2 are added together*

(Add one two)

In the function body of the add operation, use belta to convert x and y to one and two.

(Lambda (s z) (one s (two s z )))

Expand one and two using alpha conversion.

(Lambda (s z) s (lambda (s z )))

; Using beta conversions (lambda (s z) s z is actually equivalent to (s z ))

Using alpha conversion replacement, replace (lambda (s z) with (s z ))

(Lambda (s z) s (s z ))))

; Using beta conversions (lambda (s z) s (s z) is actually equivalent to (s z )))

Using alpha conversion replacement, replace (lambda (s z) s (s z) with (s z )))

(Lambda (s z ))))

Note (lambda (s z) is actually three, which is what we usually call 3

Through this simple verification process, we began to feel the beauty of "Qiu odd", but I regret that I cannot give a strict mathematical proof here, maybe later.

**2. let and lambda**

For expressions (lambda (x) (* (-x 1) 2) 5), we can understand that "Apply a lambda expression to number 5 ", when calculating the expression value, we will use beta simplification to replace the form parameter in the expression with the actual parameter 5, which is equivalent to saying "Let the form parameter have a value of 5 and then run it ", to translate this sentence into a programming language is (let (x 5) (* (-x 1) 2 ). It can be seen that the lambda expression expresses the same semantics as let, so we say "let is just a lambda syntax sugar coat ".

As a simple demo, you can observe and run the following code:

*(Define (F x) (let (a (-x 1) (* a 2 )))*

(Define (G x) (* (lambda (a) (-a 1) x) 2 ))

(F 5)

(G 5)

They will get the same result

**3. Practice 1.34**

It is relatively simple. Run the following program:

(Define (square a) (* ))

(Define (f g) (g 2 ))

(F square)

(F (lambda (z) (* z (+ z 1 ))))

The output result is 4 and 6.

If you want to evaluate (f), expand it in the application order:

(F) => (f 2) => (f (2) obviously there is a syntax error: you cannot apply the previous 2 as a function to the next 2.

**4. Fixed Point**

The algorithm for finding the zero Point on the SiC object comes from the semi-query, which is relatively simple. Here we skip it and look at the Fixed Point directly ).

A number*X*Is called*Fixed point*Of a function*F*If*X*Satisfies the equation*F*(*X*) =*X*. For some functions*F*We can locate a fixed point by beginning with an initial guess and applying*F*Repeatedly, f (x), f (x ))).... Until the value does not change very much.

Through this passage, we understand the following points:

- The fixed point is f (x) = x, that is, it maps to itself.
- It is the intersection of the function curve y = f (x) and y = x. If there is no intersection, then the function f (x) has no fixed point, such as f (x) = x + 2.
- If we can convert a problem into the form of f (x) = x, then the solution to this problem is actually to find the fixed point of f (x.
- The fixed point is to find the recursive function f (f... (F (x), the exit condition of recursion is "when the change rate of the value in the recursion process is very small ".

**5. Average Damping**

The process of calculating the fixed point always reminds people of the "Damping Oscillation" in the physics course of the second year. Although it is not the same, it is also somewhat similar. We know that in the damping oscillation, as the energy is gradually consumed, the current will gradually decrease, and the last value is 0. If the energy is continuously supplied cyclically, it will not stop Oscillating in a range. In the same way, in the process of finding a fixed point, we hope that as the number of recursion increases, the value will get closer to our expected value. On the contrary, if it stays between several values, our recursive functions form infinite recursion.

For example, if the value is always oscillating between f (n) = 1 and f (n + 1) = 2, the sequence of values is 1 2 1 2... When we change f (n + 1) to the average value of f (n) and its value, the sequence of values will become 1 1.5 1.25 1.125... Obviously, this series is converged. The average damping technology is used to modify the f (n + 1) value.

**6. Practice 1.35**

It is proved that the golden split rate is the fixed point of x-> 1 + 1/x.

When we mention the "Fixed Point" above, we say, "If we can convert a problem into the form of f (x) = x, then the solution to this problem is actually to find the fixed point of f (x). Then this question is transformed into: how to convert the golden split rate to f (x) = 1 + 1/x format.

Given that the golden split rate satisfies the equation Phi ^ 2 = Phi + 1

=> Phi = (PHI + 1)/PHI

=> Phi = 1 + 1/PHI

So that f (PHI) = 1 + 1/PHI

Therefore, if we want to find the fixed point of (?) = 1 + 1.

Calculate the golden split rate:

(Define (golden-mean x)

(Fixed-point (lambda (x) (+ 1 (/1 x) 2.0 ))

(Golden-mean 8); here x returns the same result using any positive number.

The calculation result is 1.6180327868852458 (the reciprocal is 0.6180344478216819)

**7. Exercise 1.36**

It must be proved that the root x-> log (1000)/log (x) of x ^ x = 1000 is very simple. Take the logarithm of both sides of the x ^ x = 1000 equation at the same time, then follow the exercise 1.35 method to prove it.

For details about the calculation process, refer to the following code:

(Define tolerance 0.00001)

(Define (close-enough? V1 v2)

(<(Abs (-v1 v2) tolerance ))

(Define (average v1 v2)

(/(+ V1 v2) 2 ))

(Define (fixed-point f first-guess)

(Define (try guess step-count)

(Begin

(Display "step ")

(Display step-count)

(Display ":")

(Display guess)

(Newline)

(Let (next (f guess )))

(If (close-enough? Guess next)

Next

(Try next (+ step-count 1 ))))))

(Try first-guess 0 ))

(Define (F x)

(Fixed-point (lambda (x) (/(log 1000) (log x) 2.0 ))

(Define (G x)

(Fixed-point (lambda (x) (average x (/(log 1000) (log x) 2.0 ))

(F 1, 1000)

(G 1000)

Among them, F does not adopt the average damping technology, while G does. Compare the calculation results of the two:

Step0: 2.0

Step 1: 9.965784284662087

Step 2: 3.004472209841214

Step 3: 6.279195757507157

Step 4: 3.759850702401539

Step 5: 5.215843784925895

Step 6: 4.182207192401397

Step 7: 4.8277650983445906

Step 8: 4.387593384662677

Step 9: 4.671250085763899

Step 10: 4.481403616895052

Step 11: 4.6053657460929

Step 12: 4.5230849678718865

Step 13: 4.577114682047341

Step 14: 4.541382480151454

Step 15: 4.564903245230833

Step 16: 4.549372679303342

Step 17: 4.559606491913287

Step 18: 4.552853875788271

Step 19: 4.557305529748263

Step 20: 4.554369064436181

Step 21: 4.556305311532999

Step 22: 4.555028263573554

Step 23: 4.555870396702851

Step 24: 4.555315001192079

Step 25: 4.5556812635433275

Step 26: 4.555439715736846

Step 27: 4.555599009998291

Step 28: 4.555493957531389

Step 29: 4.555563237292884

Step 30: 4.555517548417651

Step 31: 4.555547679306398

Step 32: 4.555527808516254

Step 33: 4.555540912917957

4.555532270803653

Step0: 2.0

Step 1: 5.9828921423310435

Step 2: 4.922168721308343

Step 3: 4.628224318195455

Step 4: 4.568346513136242

Step 5: 4.5577305909237005

Step 6: 4.555909809045131

Step 7: 4.555599411610624

Step 8: 4.5555465521473675

4.555537551999825

The former performs 34 operations, while the latter only performs 9 operations.

**8. Practice 1.37**

It is a little more complicated to calculate the golden split rate by using "K items with poor hyphens" than the previous exercises. The thinking process is too difficult to explain. Let's take a look at the following code:

(Define (cont-frac n d k)

(Cont-frac-iter n d k 0 (/(n 1) (d 1 ))))

Cont-frac iteration form. I indicates the number of current iterations. When it is greater than K, it jumps out of iteration.

; Result is used as the accumulate tool for iteration results. The initial value of the accumulate tool is the value when k is 1 (/(n 1) (d 1 ))

(Define (cont-frac-iter n d k I result)

(If (> I k)

Result

; First obtain the next value next

(Let (next (cont-frac-iter n d k (+ I 1) result )))

; Evaluate the value of this time

(Cont-frac-iter n d k (+ I 1) (/(n I) (+ (d I) next ))))))

; K can achieve four precision when 3 is used

(Cont-frac (lambda (I) 1.0) (lambda (I) 1.0) 3)

Calculation Result: 0.6180338134001252

**9. Practice 1.38**

Calculate the natural logarithm e by using K-item finite connected Fraction

Based on exercise 1.37, the difference is that d (I) is a series about I: 1 2 1 1 4 1 6 1 8 ....

The key is to write a function that can generate the I-th item of d (I:

(Define (mod x y) (floor (/x y )))

(Define (D I)

(If (= 0 (remainder (+ I 1) 3 ))

(* 2 (mod (+ I 1) 3 ))

1 ))

Mod modulo and remainder for remainder.

Enter D (I) into cont-frac in exercise 1.37.

**10. Practice 1.39**

Similar to the preceding solution:

(Define (cont-cf x k)

(/X (cont-cf-iter x k 1 (-1 (* x )))))

(Define (cont-cf-iter x k I result)

(If (> I k)

Result

(Let (next (cont-cf-iter x k (+ I 1) result )))

(Cont-cf-iter x k (+ I 1) (-(+ 1 (* I 2) (/(* x) next ))))))

__Note: This is a reading note, so the content only belongs to the personal understanding, and does not represent the opinions of SiC. As the understanding goes deeper, the content may be modified.__