我是 lisp 的新手,正在处理一个家庭作业问题以展平嵌套列表。我有我的功能,除了它需要“删除”点对。所以给定 (1 (2 3) (4 . 5) ((6 7) (89))) 我的函数应该输出 (1 2 3 4 5 6 7 8 9)。
所以..我的实际问题..
给定一个点对,例如 (1 . 2)
,我怎样才能得到列表 '(1 2)
?
最佳答案
cons cell 是一个由两部分组成的结构,称为 car
及其 cdr
.这对 (1 . 2)
是一个 cons 单元格,其 car
是1
谁的cdr
是2
. Lisps 中的列表由 cons 单元格和 nil
构建而成.很多地方都描述了这是如何工作的,包括对 Recursive range in Lisp adds a period? 的回答。列表是空列表 ()
(也称为 nil
),或 car
的缺点是列表的第一个元素,其 cdr
是另一个列表,它是列表的其余部分。这意味着一个列表
(1 2)
由 cons 单元和 nil
构成作为
(cons 1 (cons 2 nil))
如果你已经有了 (1 . 2)
, 那么你可以得到 1
和 2
与 car
和 cdr
.你会按照刚才的描述把它们放回去。也就是说,
(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)
关于lisp - 将点对转换为 LISP 中的双元素列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21682677/