我正在学习 Lisp,但我没有 Lisp 编程经验。在我的部分研究中,我遇到了以下示例:
> (cons ‘a ‘(a b)) ----> (A A B)
> (cons ‘(a b) ‘a) ----> ((A B).A)
我想知道为什么当我们有 (cons 'a '(a b)) 时响应是 (A A B) 以及为什么当我们稍微改变它并把'a 在(a b) 之后,响应是一个虚线列表,如((A B).A)?第一个代码行和第二个代码行有什么区别?这些代码背后发生了什么?
最佳答案
如果你把它们想象成cons-cells就很容易理解了.
简而言之,cons 单元格由正好 两个值组成。通常的表示法是使用点,例如:
(cons 'a 'b) ==> (A . B)
但是由于在 LISP 中经常使用列表,所以更好的表示法是去掉点。
列表是通过让第二个元素成为一个新的 cons 单元格,最后一个结束符作为终止符(通常是 nil,或 Common Lisp 中的 '()
)来创建的。所以这两个是相等的:
(cons 'a (cons 'b '())) ==> (A B)
(list 'a 'b) ==> (A B)
因此 (cons 'a 'b)
创建了一个单元格 [a,b]
,而 (list 'a 'b)
将创建 [a, [b, nil]]
。请注意 cons 单元格中编码列表的约定:它们以内部 nil
结束。
现在,如果您将 'a
添加到最后一个列表中,您将创建一个包含 [[a, [b, nil]], a]
的新 cons 单元格。因为这不是一个“正确的”列表,即它没有以 nil
结尾,所以写出它的方法是使用点:(cons '(a b) 'a) = => ((a b) . a)
.
如果没有打印点,则它必须是具有结构 [[a, [b, nil]], [a, nil]]
的列表。
你的例子
当你执行 (cons 'a '(a b))
时,它将采用符号 'a
和列表 '(a b)
并把他们放在一个新的牢房里。所以这将由 [a, [a, [b, nil]]]
组成。因为这自然以内部 nil
结尾,所以它没有点。
至于(cons '(a b) 'a)
,现在你会得到[[a, [b, nil]], a]
。这不会以内部 nil
终止,因此将使用点符号。
我们可以使用 cons 使最后一个示例以内部 nil 结尾吗?是的,如果我们这样做
(cons '(a b) (cons 'a '())) ==> ((A B) A)
最后,
(list '(a b) 'a))
相当于
(cons (cons (cons 'a (cons 'b '())) (cons 'a '())))
关于lisp - "Cons"在 Lisp 中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29703516/