【问题标题】:Racket Lisp : comparison between new-if and ifRacket Lisp:new-if 和 if 之间的比较
【发布时间】:2012-09-09 07:05:36
【问题描述】:
(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 替换为 new-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 被证明是错误的,因为当我尝试时它是一个死循环。

那么,为什么?

【问题讨论】:

  • 请注意,这是一道 SICP 题,练习 1.6。考虑应用顺序评估对 new-if 使用的影响。

标签: lisp scheme racket sicp


【解决方案1】:

new-if 是一个函数。函数的所有参数都在调用函数之前进行评估。但是sqrt-iter是递归函数,需要避免在参数已经足够好的情况下进行递归调用。

内置的if是语法,根据条件的值只计算then-branch或else-branch。

你可以用宏写new-if

【讨论】:

  • 确实,只需将 define 声明的 define-syntax-rule 更改为 define-syntax-rule,它就会按预期工作。 (假设您使用的是#lang racket
  • “语法”有点不精确。 If 是一个特殊运算符
  • Racket 看起来像 Scheme 方言,Scheme 使用术语“语法”。
  • 就是这样!我得到了它。这意味着在 new-if 之前,递归结构已经运行。所以这是一个死循环。但是如果只是按照正常顺序,只是先评估足够好,然后再做出选择。谢谢!
【解决方案2】:

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

如果您之前没有尝试过代数步进器,请查看此answer 以了解它的外观。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-01
      • 2020-05-28
      相关资源
      最近更新 更多