我正在尝试编写一个小的递归程序来测试列表,如果每个元素都是一个原子,则返回 t 。我遇到的问题是,当函数收到一个空列表时,它会返回 t 而不是 nil 的结果。我无法想出一种方法让它返回 nil 作为最初的空列表,并且仍然以递归方式正常运行。
(defun only-atoms (in)
(if (null in)
t
(and (atom (first in)) (only-atoms (cdr in)) )
)
)
答案 0 :(得分:2)
该函数可以在没有使用例如递归的情况下实现。 every
,如:
(defun only-atoms (list)
(and list (every #'atom list)))
当涉及到你所陈述的问题时,当使用空列表调用函数时,函数返回T
而不是NIL
的所需结果:
如果T
为真,您的递归实现会显式返回(null in)
,这可以解释您的发现。只需将其更改为所需的值NIL
即可。考虑将if
结构更改为and
。
仅当列表包含多个项目时才进行递归调用。 (rest in)
的测试很好。如果列表位于最后一项,则提供真值而不是进行递归调用。
小心地找到only-atoms
调用以确保该函数可以是尾递归的。
例如:
(defun only-atoms (list)
(and list
(atom (first list))
(or (null (rest list))
(only-atoms (rest list)))))
答案 1 :(得分:1)
使用COND,它允许您测试几种情况:
答案 2 :(得分:1)
空列表 满足每个元素都是原子的条件!您要求它至少包含一个元素是附加要求。
表达“列表的每个元素都是原子”的最简单方法是(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)))))
答案 3 :(得分:0)
此解决方案正常运行:
(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)))
答案 4 :(得分:-1)
您可以将函数拆分为两个,并在输入递归之前提供初始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)))