递归检查列表中的原子

时间:2011-04-19 06:00:32

标签: recursion common-lisp

我正在尝试编写一个小的递归程序来测试列表,如果每个元素都是一个原子,则返回 t 。我遇到的问题是,当函数收到一个空列表时,它会返回 t 而不是 nil 的结果。我无法想出一种方法让它返回 nil 作为最初的空列表,并且仍然以递归方式正常运行。

(defun only-atoms (in)
  (if (null in)
    t
    (and (atom (first in)) (only-atoms (cdr in)) )
  )
)

5 个答案:

答案 0 :(得分:2)

该函数可以在没有使用例如递归的情况下实现。 every,如:

(defun only-atoms (list)
  (and list (every #'atom list)))

当涉及到你所陈述的问题时,当使用空列表调用函数时,函数返回T而不是NIL的所需结果:

  1. 如果T为真,您的递归实现会显式返回(null in),这可以解释您的发现。只需将其更改为所需的值NIL即可。考虑将if结构更改为and

  2. 仅当列表包含多个项目时才进行递归调用。 (rest in)的测试很好。如果列表位于最后一项,则提供真值而不是进行递归调用。

  3. 小心地找到only-atoms调用以确保该函数可以是尾递归的。

  4. 例如:

        (defun only-atoms (list)
          (and list
              (atom (first list))
              (or (null (rest list))
                  (only-atoms (rest list)))))
    

答案 1 :(得分:1)

使用COND,它允许您测试几种情况:

  • 空列表 - >零
  • 一个元素列表 - >原子? ;提示:不要使用LENGTH
  • 其他 - >原子?第一个元素和rest元素的递归调用

答案 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)))