练习 1.3
Exercise 1.3. Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
这题定义的过程要求求出三个数中两个最大数字的平方和,如果先求出两个最大数,然后分别求平方再求和在实现上比较麻烦,可先求出三个数平方和之 后减去最小数的平方,则只需要实现过程 smaller 求出最小数字即可。
最终在 DrRacket 环境下的实现:
(define sum-of-squares (lambda (x y z) (+ (* x x) (* y y) (* z z))))
(define (smaller x y z)
(cond ((and (< x y) (< x z)) x)
((and (< y x) (< y z)) y)
(else z)))
(define (bigger-sum-of-squares x y z)
(- (sum-of-squares x y z) (* (smaller x y z) (smaller x y z))))
练习 1.5
Exercise 1.5. Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))Then he evaluates the expression
(test 0 (p))
What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)
如果是 normal-order evaluation 的话,在调用 test 这个 proceudre 的时候会先对两个参数求值,第二个参数 (p) 求值会使解释器进入死循环,不停调用自身。但如果是 applicative-order 的话,解释器并不会对 (p) 求值,而是直接返回 0。
练习 1.6
Exercise 1.6. Alyssa P. Hacker doesn’t see why if needs to be provided as a special form. “Why can’t I just define it as an ordinary procedure in terms of cond?” she asks. Alyssa’s friend Eva Lu Ator claims this can indeed be done, and she defines a new version of if:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))Eva demonstrates the program for Alyssa:
(new-if (= 2 3) 0 5)
5(new-if (= 1 1) 0 5)
0Delighted, Alyssa uses new-if to rewrite the square-root program:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))What happens when Alyssa attempts to use this to compute square roots? Explain.
首先尝试用题目中所给的 new-if 过程来写 sqrt 并尝试运行
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(define (improve guess x)
(average guess (/ x guess)))
(define (average x y)
(/ (+ x y) 2))
(define (square guess) (* guess guess))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (sqrt x)
(sqrt-iter 1.0 x))
然后尝试调用 (sqrt 9)
,发现程序死循环了。原因是 scheme 中的 if 的求值方法是,先求值 predicate,如果为 True 则求值 then-clause,否则求值 else-clause,但是由于解释器的实现是 applicative-order,所以 new-if 中的求值方法是直接对 predicate then-clause else-clause 求值,这就导致程序进入了死循环。
练习 1.11
Exercise 1.11. A function f is defined by the rule that f(n) = n if n<3 and f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) if n> 3. Write a procedure that computes f by means of a recursive process. Write a procedure that computes f by means of an iterative process.
递归的写法很简单,采用迭代计算过程,首先考虑递归展开树,发现和斐波拉契数列展开树很相似,可以把 f(n - 1)、f(n - 2)、f(n - 3) 三个数字存在变量里避免重复计算结点,最终得到的迭代计算过程:
(define (f n)
(if (< n 3)
n
(f-iter 0 1 2 0 (- n 3))))
(define (f-iter last3 last2 last1 i n)
(if (= i n)
(+ last1 (* 2 last2) (* 3 last3))
(f-iter last2
last1
(+ last1 (* 2 last2) (* 3 last3))
(+ i 1)
n)))