Racket Lisp:new-if和if之间的比较


(define (sqrt-iter guess x)
    (if (good-enough? guess x)
        guess
        (sqrt-iter(improve guess x)
                  x)))
(define (improve guess x)
  (average guess(/ x guess)))
(define (average x y)
  (/ (+ x y) 2))
(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.0001))
(define (square x)
  (* x x))
(define (sqrt-g x)
  (sqrt-iter 1.0 x))

这是一个适用于 sqrt 的程序。问题是当你尝试使用 new-if 替换 if 时会发生什么。

(define (sqrt-iter guess x)
    (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)))

我的观点是两个程序将相同的结果。 因为new-if和if可以产生相同的结果。

然而,new-if被证明是错误的,因为我尝试时这是一个死圈。

那么,为什么呢?

>new-if是一个函数。在调用函数之前,将计算函数的所有参数。但是sqrt-iter是一个递归函数,当参数已经足够好时,你需要避免进行递归调用。

内置if是语法,仅计算当时的分支或 else 分支,具体取决于条件的值。

您可以使用宏编写new-if .

这是演示代数步进器的完美示例!在代数步进器中,您可以看到计算过程与您的期望有何不同。在这里,您必须注意(new-if 1 2 3)和(if 1 2 3)的评估差异。

如果您以前没有尝试过代数步进器,请参阅此答案以了解它的外观。

由于球拍是一种应用程序,因此new-if的第三个参数是(sqrt-iter(improve guess x) x))。由于sqrt-iter是递归的,因此第三个参数永远不会为其赋值。因此,您永远不会进入new-if来评估函数的过程。

最新更新