首页 > 解决方案 > 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后记。因为它看起来显然是逻辑正确的。

请问可以给点提示吗?

标签: lispelispsicp

解决方案


版本没有问题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)))

推荐阅读