lisp - max-lisp-eval-depth 找到 sqrt-iter
问题描述
我正在研究 SICP 的练习 1.6,它重写了演示案例
#+begin_src emacs-lisp :session sicp :results output
(defun sqrt(x)
(sqrt-iter 1.0 x))
(defun sqrt-iter(guess x)
(if (good-enough-p guess x)
guess
(sqrt-iter (improve guess x)
x)))
(defun good-enough-p(guess x)
(< (abs (- (square guess) x)) 0.001))
(defun improve(guess x)
(average guess (/ x guess)))
(defun average(x y)
(/ (+ x y) 2))
#+end_src
它可以工作并获得输出
#+begin_src emacs-lisp :session sicp :lexical t :results output
(print (sqrt 11))
(print (sqrt (+ 100 37)))
(print (sqrt (+ (sqrt 2) (sqrt 3))))
#+end_src
#+RESULTS:
:
: 3.3166248052315686
:
: 11.704699917758145
:
: 1.7739279023207892
因此来到练习 1.6,将其重写为cond
#+begin_src emacs-lisp :session sicp :lexical t
(defun sqrt-iter-cond(guess x)
(cond ((good-enough-p guess x) guess)
(t (sqrt-iter-cond (improve guess x) x))
)
)
(sqrt-iter-cond 1 10)
#+end_src
它报告错误:
ob-async-org-babel-execute-src-block: Lisp nesting exceeds ‘max-lisp-eval-depth’
看了各种解释后,我陷入了更多的困惑,甚至产生了一种隐含的恐惧来使用cond
后记。因为它看起来显然是逻辑正确的。
请问可以给点提示吗?
解决方案
版本没有问题cond
,从一个空缓冲区开始,试试这个,它会工作:
(defun sqrt (x)
(sqrt-iter-cond 1.0 x))
(defun sqrt-iter-cond (guess x)
(cond ((good-enough-p guess x) guess)
(t (sqrt-iter-cond (improve guess x) x))))
(defun good-enough-p (guess x)
(< (abs (- (square guess) x)) 0.001))
(defun improve (guess x)
(average guess (/ x guess)))
(defun average(x y)
(/ (+ x y) 2))
(print (sqrt 11))
=> 3.3166247903554
但是这个练习不是关于用 重写程序cond
,它应该告诉你你不能编写你自己的if
使用程序版本,并且你需要一个带有特殊评估规则的特殊形式 - 因为程序的评估规则将同时评估随之而来的部分和替代部分同时进行,那将行不通!看看这个简单的例子,明白我的意思:
(if t 'ok (/ 1 0))
上面将返回'ok
,即使那里有一个除以零:那部分从未被执行。但是,如果我们尝试将我们自己的if
实现作为正常程序执行,它将失败并出现除以零错误:
(defun my-if (condition consequent alternative)
(cond (condition consequent)
(t alternative)))
(my-if t 'ok (/ 1 0))
现在回到您的代码并尝试一下,当然它也会失败,但这次出现无限递归错误(这就是“Lisp 嵌套超过 'max-lisp-eval-depth'”消息的含义):
(defun sqrt-iter (guess x)
(my-if (good-enough-p guess x)
guess
(sqrt-iter (improve guess x)
x)))
推荐阅读
- c++ - 为什么数学公式在 C++ 中不起作用?
- azure-ad-b2c - 使用服务器地址时 Azure B2C 重定向 url 不起作用
- c - 使用哈希表对字典中的每个单词进行排序......由于某种原因,链表填充了相同的单词
- azure - 注册期间在联系信息中存储“电子邮件” - Azure AD B2C 自定义策略
- android - 如何在主题中设置 TextInputLayout 的hintTextColor 样式?
- html - 如何在 div 元素上触发点击事件并显示其相邻元素 JQUERY
- flutter - PageView 导航按钮需要点击 2 次才能实际工作 (Flutter)
- java - 如何在 Neptune 中使用 Gremlin 会话?
- python - 我的 Python 代码有问题。有错误,“未解决的参考”
- github - Github 工作流如何读取托管在同一 GitHub 帐户上的另一个私有存储库中的文件?