sicp-answer~> 1-6

自己定义的 new-if 过程:

(define (new-if predicate then-clause else-clause)
  (cond (predicate then-clause)
        (else else-clause)))

(new-if (= 2 3) 0 5)
; 5

(new-if (= 1 1) 0 5)
; 0

当用 new-if 编写求平方根时:

(define (sqrt-iter guess x)
  (new-if (good-enough? guess x)
    guess
    (sqrt-iter (improve guess x) x)))

此时会发生什么呢......答案是会爆栈/递归深度过大
1-5 中明确说过, if 是一个特殊形式的 惰性 的过程, 与普通过程不同
而这里的 new-if, 是个自己定义的普通过程, 而非编译器提供的特殊过程

因此, 每次调用 sqrt-iter, 其实都会求值第二分支中的 (sqrt-iter (improve guess x) x)
而该第二分支的求值又会再次求值其第二分支的表达式......

那么, 你可能又要问了:

(new-if (= 2 3) 0 5)
; 5

(new-if (= 1 1) 0 5)
; 0

先前的这部分代码, new-if 看起来不是只返回了一个值吗? 为什么你说是两个都求值?
如果两个都求值的话, 难道不会在 REPL 中打印 05 吗?

no, no, no, 虽然 new-if 在接收参数时对每个参数都求值了, 但是其内部定义是个 cond, 其只会返回某个单一的表达式
我们可以添加一点副作用(输入输出等)来进行验证:


(new-if #t (display 1) (display 2))
; 12

(if #t (display 1) (display 2))
; 1

new-if 在接收参数时便进行了求值, 因此打印输出了 12
而 if 是先判断条件再选取分支进行求值, 因此只打印输出了 1


上一篇: 1-5
下一篇: 1-7