【发布时间】:2019-07-09 14:09:14
【问题描述】:
我决定整理以下函数。这个想法是它使用cond,但它也包含ifs,这使得认知处理变得困难。这是 ansi common lisp 一书中的 bst 代码。
(defun percolate (bst)
(cond ((null (node-l bst))
(if (null (node-r bst))
nil
(rperc bst)))
((null (node-r bst)) (lperc bst))
(t (if (zerop (random 2))
(lperc bst)
(rperc bst)))))
我的想法是通过在cond 中添加更多案例来删除 ifs,然后用左边的原因很好地证明整个事情,右边的效果。
这是我想出的:
(defun percolate (bst) ; [6,7,7a]
(cond (((and (null (node-l bst)) (null (node-r bst))) nil)
((null (node-l bst)) (rperc bst))
((null (node-r bst)) (lperc bst))
(t (if (zerop (random 2))
(lperc bst)
(rperc bst))))))
但是,这会产生错误
*** - SYSTEM::%EXPAND-FORM: (AND (NULL (NODE-L BST)) (NULL (NODE-R BST))) should be a
lambda expression
我可以在堆栈溢出上找到其他有关此问题的帖子,例如here,但我仍然不明白。 cond 是否以某种方式偏离了正常的 lisp 语法?我想确定我所做的假设是错误的。
为了记录,下面的代码被解释器接受了,但显然我们不想这样写。
(defun percolate (bst) ; [6,7,7a]
(let ((both-null (and (null (node-l bst)) (null (node-r bst))))
(l-null (null (node-l bst)))
(r-null (null (node-r bst))))
(cond ((both-null nil)
(l-null (rperc bst))
(r-null (lperc bst))
(t (if (zerop (random 2))
(lperc bst)
(rperc bst)))))))
【问题讨论】:
-
您可能想考虑换一种方式:
(random-elt (delete nil (vector left right))) -
我认为他的渗滤液中的
random位是错误的,正如书中勘误表中所解释的那样。有人评论说“删除的内部节点需要被左子树中的最大节点或右子树中的最小节点替换,而你的函数不这样做”......但我还没有完全理解还没有......但我的帖子只是关于语法...... :)
标签: common-lisp