在LISP中将点对转换为双元素列表

时间:2014-02-10 16:31:05

标签: lisp common-lisp

我是lisp的新手并且正在处理作业问题以展平嵌套列表。我有我的功能工作,除了它需要'删除'点对。所以给定(1(2 3)(4.5)((6 7)(89)))我的函数应输出(1 2 3 4 5 6 7 8 9)。

所以..我的实际问题..

如果有一对虚线对,例如(1 . 2),我该如何获取列表'(1 2)

1 个答案:

答案 0 :(得分:7)

cons单元是一个由两部分组成的结构,称为car及其cdr。对(1 . 2)是一个缺点单元格,其car1且其cdr2。 Lisps中的列表是由cons单元格nil构建的。如何在多个地方描述其工作原理,包括Recursive range in Lisp adds a period?的答案。列表是空列表()(也称为nil),或者是car的利弊是列表的第一个元素,其cdr是另一个列表,列表的其余部分。这意味着一个列表

(1 2)

由缺点单元格构建,nil

(cons 1 (cons 2 nil))

如果您已经(1 . 2),那么您可以12获得carcdr。如上所述,你将它们重新组合在一起。也就是说,

(let ((x '(1 . 2)))
  (cons (car x) (cons (cdr x) nil)))

或者,您可以使用list

(let ((x '(1 . 2)))
  (list (car x) (cdr x)))

如果您想重复使用相同的cons单元格,则可以使用cdr替换单元格的(cons 2 nil)。例如(并注意我们不再引用该对,因为修改文字数据是未定义的行为):

(let ((x (cons 1 2)))
  (setf (cdr x) (cons (cdr x) nil))
  x)

那也可能是

(let ((x (cons 1 2)))
  (setf (cdr x) (list (cdr x)))
  x)

您也可以使用rplacd

(let ((x (cons 1 2)))
  (rplacd x (list (cdr x)))
  x)