递归检查列表中的原子

发布于 2024-11-02 08:17:21 字数 317 浏览 1 评论 0原文

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

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

I am attempting to write a small recursive program that tests a list and returns t if every element is an atom. The problem I am having is that when the function receives an empty list, it returns t instead of the desired result of nil. I cannot come up with a way to have it return nil for an initially empty list and still function properly in a recursive manner.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

£冰雨忧蓝° 2024-11-09 08:17:21

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

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

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

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

  2. 仅当列表有多个项目时才进行递归调用。对 (rest in) 进行适当的测试就可以了。如果列表位于最后一项,则提供真值而不是进行递归调用。

  3. 仔细找到 only-atoms 调用以确保该函数可以尾递归。

例如:

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

The function can be implemented without recursion using e.g. every, as in:

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

When it comes to your stated problem that the function returns T instead of the desired result of NIL when the function is called with an empty list:

  1. Your recursive implementation explicitly returns T if (null in) is true, which explains your finding. Simply change it to the desired value NIL. Consider changing the if construct to and.

  2. Only make the recursive call when the list has more than one item. A well placed test for (rest in) will do. Provide a true value instead of making the recursive call if the list is at its last item.

  3. Carefully locate the only-atoms call to ensure that the function can be tail-recursive.

For example:

    (defun only-atoms (list)
      (and list
          (atom (first list))
          (or (null (rest list))
              (only-atoms (rest list)))))
岁月流歌 2024-11-09 08:17:21

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

  • 空列表 -> nil
  • 一个元素列表 ->原子? ;提示:不要使用 LENGTH
  • else ->原子?对于第一个元素和其余元素的递归调用

Use COND, which allows you to test for several cases:

  • empty list -> nil
  • one element list -> atom? ; hint: don't use LENGTH
  • else -> atom? for first element and recursive call for rest elements
失而复得 2024-11-09 08:17:21

空列表确实满足每个元素都是原子的条件!您要求它至少包含一个元素是一项附加要求。

表达“列表中的每个元素都是一个原子”的最简单方法是(every #'atom list)。您可以使用 将其与您的附加要求结合起来。

如果您坚持以 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)))))

The empty list does fulfill the condition that every element is an atom! Your requirement that it should contain at least one element is an additional requirement.

The simplest way to express "every element of the list is an atom" is (every #'atom list). You can combine it with your additional requirement with and.

If you insist on doing it recursively in SICP-style, separate your requirements:

(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)))))
薔薇婲 2024-11-09 08:17:21

这个解决方案工作正常:

(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)))

This solution works correctly:

(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)))

However a much more elegant solution(with no recursion) would be:

(defun lat-p (lst)
           (and lst (every #'atom lst)))
多情癖 2024-11-09 08:17:21

您可以将函数分成两部分,并在进入递归之前提供初始 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)))

You can split your function in two, and provide the initial nil screening before you enter recursion. The following code is one way to do so (I tried to keep it as close to provided code as possible):

(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)))

This is also a good opportunity to make your function tail recursive:

(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)))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文