我试图写的一个小程序递归,测试列表并返回吨如果每一个元素是一个原子。我遇到的问题是,当功能模块的空列表,则返回吨代替的零期望的结果。我不能想出一个办法把它返回零一个最初为空列表和递归的方式仍然正常工作。递归检查原子列表中的
(defun only-atoms (in)
(if (null in)
t
(and (atom (first in)) (only-atoms (cdr in)))
)
)
我试图写的一个小程序递归,测试列表并返回吨如果每一个元素是一个原子。我遇到的问题是,当功能模块的空列表,则返回吨代替的零期望的结果。我不能想出一个办法把它返回零一个最初为空列表和递归的方式仍然正常工作。递归检查原子列表中的
(defun only-atoms (in)
(if (null in)
t
(and (atom (first in)) (only-atoms (cdr in)))
)
)
功能可以不使用递归来实现,例如every
,如:
(defun only-atoms (list)
(and list (every #'atom list)))
当涉及到的功能,当函数调用一个空列表返回T
而不是NIL
期望的结果您所陈述的问题:
你的递归如果(null in)
为真,则实施明确返回T
,这解释了您的发现。只需将其更改为所需值NIL
即可。考虑将if
结构更改为and
。
只会使递归调用时,列表中有多个项目。对于(rest in)
将进行良好的测试。如果列表位于最后一项,则提供一个真正的值而不是进行递归调用。
仔细查找only-atoms
通话,以确保功能可尾递归。
例如:
(defun only-atoms (list)
(and list
(atom (first list))
(or (null (rest list))
(only-atoms (rest list)))))
可以一分为二的功能,并输入递归之前提供初始nil
筛选。下面的代码是这样做的一种方式(我试图保持它接近提供的代码越好):
(defun only-atoms (in)
(defun only-atoms-iter (in)
(if (null in)
t
(and (atom (first in)) (only-atoms-iter (cdr in)))))
(unless (null in)
(only-atoms-iter in)))
这也是一个很好的机会,让你的函数尾递归:
(defun only-atoms (in)
(defun only-atoms-iter (in state)
(if (null in)
state
(only-atoms-iter (cdr in) (and state (atom (first in))))))
(unless (null in)
(only-atoms-iter in t)))
使用COND,它允许你来测试几种情况:
该解决方案正常工作:
(defun lat-p (lst)
(labels ((lat-p* (lst)
(cond
((null lst) t)
((atom (car lst)) (lat-p* (cdr lst)))
(t nil))))
(if lst
(lat-p* lst)
nil)))
然而一个更优雅的解决方案(无递归)将是:
(defun lat-p (lst)
(and lst (every #'atom lst)))
空列表不满足的条件,每一个元素是一个原子!您的要求至少应包含一个元素,即附加的要求。
表达“列表的每个元素都是原子”的最简单方法是(every #'atom list)
。您可以将其与and
的额外要求结合使用。
如果你坚持在SICP式递归做,分开你的要求:
(defun not-empty-and-all-atoms (list)
(and list
(all-atoms list)))
(defun all-atoms (list)
(if (endp list)
t
(and (atom (first list))
(all-atoms (rest list)))))
嵌套DEFUNs是错误的。对于本地功能使用FLET或标签。不,如果你不知道自己在做什么和/或你是否正在使用Scheme编程,请避免tailrecursion。 – 2011-04-19 06:24:34
我知道我应该添加关于我不太熟悉CL的评论。我主要与Scheme合作,并对此进行了评论。我的错。 :)但是,我不认为这会使主要答案无效:先检查,稍后再检查。 – vhallac 2011-04-19 06:26:57
Scheme允许嵌套DEFINE,在Lisp嵌套的DEFUNS中是错误的,不会做你认为他们做的事。 – 2011-04-19 06:28:33