scheme - 重新定义`if`时无休止的递归,为什么?
问题描述
我是编程新手,开始学习语言方案。(我研究了《计算机程序的结构和解释》一书),遇到了一项任务,如下所述。我写了两个代码替换if
为cond
,但是由于某种原因,在运行第一个代码时存在无限递归,但是在运行第二个代码时没有无限递归,它通常会计算sqrt ...虽然代码是相同的,为什么会这样?
Alyssa P. Hacker 不明白为什么
if
需要以特殊形式提供。“为什么我不能把它定义为一个普通的程序cond
?” 她问。Alyssa 的朋友 Eva Lu Ator 声称这确实可以做到,她定义了一个新版本if
:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Eva 演示了 Alyssa 的程序:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
很高兴,Alyssa 用它
new-if
来重写square-root
程序:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
当 Alyssa 尝试使用它来计算平方根时会发生什么?解释。
第一个代码:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
(define (square x)
(* x x))
(define (average x y)
(/ (+ x y) 2))
(define (improve guess x)
(average guess (/ x guess)))
(define (better-good-enough? prev-guess guess)
(< (abs (- guess prev-guess))
0.00001))
(define (better-sqrt-iter prev-guess guess x)
(new-if (better-good-enough? prev-guess guess)
guess
(better-sqrt-iter guess
(improve guess x)
x)))
(define (better-sqrt x)
(better-sqrt-iter 0 1.0 x))
第二个代码:
(define (square x)
(* x x))
(define (average x y)
(/ (+ x y) 2))
(define (improve guess x)
(average guess (/ x guess)))
(define (better-good-enough? prev-guess guess)
(< (abs (- guess prev-guess))
0.00001))
(define (better-sqrt-iter prev-guess guess x)
(cond ((better-good-enough? prev-guess guess)
guess)
(else (better-sqrt-iter guess
(improve guess x)
x))))
(define (better-sqrt x)
(better-sqrt-iter 0 1.0 x))
解决方案
这听起来像是一个家庭作业问题,但是,假设您使用的是 Scheme,请考虑当一般形式(所以,不是任何特殊形式)像
(f a b c)
被评估:
f
,a
,b
&c
以某种未定义的顺序进行评估(甚至可能同时进行);- 应该是一个函数的
f
(换句话说,评估它的结果)的值应用于评估的结果a
,b
&c
; - 该函数返回一个值(或多个值),这是表单的值。
当您使用此评估策略尝试评估 的第一个版本时会发生better-sqrt-iter
什么?您可以用纸和铅笔手工进行一些评估,看看会发生什么。
为什么该评估规则在这里存在问题?
推荐阅读
- angular - 如何将数据从一个 Angular 4 应用程序传递到另一个?
- python - 如何在 WSGI 服务器上使用动态/adhoc 服务器监听套接字?
- graphql - 在 GraphQL typedDefs 中使用联合类型
- c# - C#从鼠标光标的位置获取各种东西
- json - Ansible - 在 url、用户名、密码上循环并生成响应文件
- search - Perl 6中不止一根针的索引
- typescript - Typescript 函数,它接受一个函数并返回一个带有参数子集的函数
- intellij-idea - 复制 IntelliJ 中的一行,然后注释掉
- animation - 这个网站的技术是什么?
- ios - 与 FBSDK 共享视频时如何显示对话框?