Common Lisp中的列表和成员实现

时间:2013-05-22 00:53:09

标签: lisp common-lisp

我刚刚开始学习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 个答案:

答案 0 :(得分:3)

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

形成的原因
nil

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

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

(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是列表的元素。

答案 1 :(得分:2)

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

()(())不同。 ()(nil)不同。

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

答案 2 :(得分: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。

答案 3 :(得分:-1)

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

(defun member2 (item lst)
  (if lst
      (if (eql item (car lst))
          T
          (member2 item (cdr lst)))))