2

我刚刚开始学习 Common Lisp,我正在阅读的文本使用了一个带有该member函数的示例。

我不确定这两个代码块之间的区别:

(if (member nil '(1 nil 2 3))
    'contains-nil
    'does-not-contain-nil)

返回 CONTAINS_NIL

(if (member nil '(1 2 3))
    'contains-nil
    'does-not-contain-nil)

返回 DOES-NOT-CONTAIN-NIL

据我了解,列表相当于嵌套cons单元格,所以我认为(member nil (cons 1 (cons 2 (cons 3 nil)))会返回(nil),但它只是返回nil。我不确定编译器或解释器如何做出这种区分,如果有人能给我一些关于如何实现该member功能的见解,我将不胜感激。

4

4 回答 4

4

一个 cons 单元格包含两个值,通常称为 itscar和 its cdr。该表达式(cons x y)返回一个 cons 单元格,其carx,其cdry。在 Lisp 中,列表要么是空列表(通常是符号nil),要么是一个 cons 单元格。当列表是 cons 单元格时,列表的第一个元素是 cons 单元格car,列表的其余部分是 cons 单元格cdr。考虑清单(1 2 3)。它是一个 cons 单元格,列表的第一个元素是1. 列表的其余部分不为空,因此它必须是另一个列表,其第一个元素是2。该列表的其余部分不为空,因此它必须是另一个列表,其第一个元素是3. 该列表的其余部分空,即nil. 基于该分析,我们可以看到为什么该列表是由

(cons 1 (cons 2 (cons 3 nil)))
== (1 2 3)

在组成列表的 cons 单元链中,列表的元素是链中每个 cons 单元的汽车值。列表可以是列表的元素,如

(cons 1 (cons nil (cons 2 (cons 3 nil))))
== (1 nil 2 3)

或者

(cons 1 (cons (cons 2 (cons 3 nil)) nil))
== (1 (2 3))

但仅仅因为我们nil在更长的表达式中看到并不意味着它nil是列表的一个元素。

于 2013-05-22T01:02:36.883 回答
2

MEMBER只查看列表的元素,而不是列表本身。空列表不同于以另一个空列表作为元素的空列表。

()不一样(())()不一样(nil)

由于列表是由 cons 单元格组成的,因此元素是 cons 单元格的元素cars

于 2013-05-22T07:35:12.420 回答
1

列表被定义为空列表 NIL 或者是一个 cons 单元,其 CAR 是列表的一个元素,其 CDR 是另一个列表。列表由

(cons 1 nil)

是一个包含元素 1 以及空列表的所有元素的列表。空列表没有元素,因此 NIL 不是列表的元素。它与集合类似:尽管空集合是任何集合的子集,但它不是每个集合的元素(虽然通常不禁止它成为集合的元素)。

实现 MEMBER 的一种方法是这样的:

(defun member (item list)
  (if list
      (if (eql item (car list))
          list
          (member item (cdr list)))))

因此,如果 LIST 为 NIL,则整个函数将返回 NIL。

于 2013-05-22T06:11:12.507 回答
-1

我们自己的 lisp 中预定义成员函数的版本可以定义为:

(defun member2 (item lst)
  (if lst
      (if (eql item (car lst))
          T
          (member2 item (cdr lst)))))
于 2021-06-03T02:27:28.973 回答