【发布时间】:2014-11-26 14:36:54
【问题描述】:
我是一个新的 lisp 程序员,我无法理解 lisp 中的递归。我有一系列表达式,我通过一系列用数字替换符号的方法来简化它们,然后我将评估表达式。在评估之前,我用符号代替数字,这样做我在我的 subst-bindings 方法中和/或当我从该方法中调用 deep-subst 方法时出现堆栈溢出错误。关于我的递归方法调用的任何帮助或建议可以帮助我更好地理解,我将不胜感激!我的代码如下--
(setq p1 '(+ x (* x (- y (/z 2)))))
(setq p2 '(+ (- z 2) (* x 5)))
(setq p3 '(+ 1 a))
(defun deep-subst (old new l)
(cond
((null l)
nil
)
((listp (car l))
(cons (deep-subst old new (car l)) (deep-subst old new (cdr l)))
)
((eq old (car l))
(cons new (deep-subst old new (cdr l)))
)
(T
(cons (car l) (deep-subst old new (cdr l)))
)
)
)
(defun subst-bindings (bindinglist exp)
(cond
( (null bindinglist)
exp )
(T
(subst-bindings (cdr bindinglist)(deep-subst (car (car bindinglist)) (cdr (car bindinglist)) exp))
)
)
)
(defun simplify (exp)
(cond
( (listp exp)
(simplify-triple (car exp) (simplify (car(cdr exp)))(simplify (car (cdr (cdr exp)))))
(T
exp))))
(defun evalexp (binding-list exp)
(simplify (subst-bindings binding-list exp))
)
(evalexp '( (x 2) (z 8) ) p1) ;Where I call evalexp from and gives me the stack overflow error
【问题讨论】:
-
如果您可以仅显示最少量的代码和重现问题的测试用例以及您收到的错误消息,将会更有帮助。 Common Lisp 还包含一个跟踪宏,因此如果您要执行
(trace deep-subst),您将看到所有对 deep-subst 的调用,您可能会发现问题。 -
我会试一试,我还取出了对发现问题没有必要或无帮助的代码。最后一行代码是我调用 evalexp 的示例测试用例
-
我想你可能想调试更多。问题似乎并非仅出现在替换函数中。例如,pastebin.com/NWHPK5PF 运行没有问题(尽管结果可能不是您期望的那样;绑定列表应该是
'((x . 2) (z . 8))吗?)。这表明simplify有问题。 -
嗯,很有趣,我没想过要把它全部删掉并单独测试,我相信你是对的,我需要仔细看看简化。
-
@Branbron 我会提到一件事;当我运行我在之前的评论中链接到的示例时,我注意到您的替换算法采用
(a . b)形式的绑定来将 a 替换为 b。在您使用的绑定中,您将用 (2) 替换 x,用 (8) 替换 z。其中每一个都是一个列表,因此您可以递归更多的结构。在那里犯错不会太难。
标签: recursion lisp common-lisp