问题描述
cons
对以下两项的作用有何不同:
(cons 1 '(2))
; (1 2)
(cons 1 2)
; (1 . 2)
两者都将 pair?
评估为真,所以我很好奇两者有何不同。
是否产生:
--------
| 1 | 2 |
-------
另一个产生:
-------- --------
| 1 | -> | | 2 | X |
------- -------
或者有什么不同?
解决方法
cons
在这两种情况下的工作方式没有区别。
cons
是一样的。 cons
产生的任何东西都会导致 pair?
返回 true
。就这么简单。
你cons
在一起的两件事在两个代码片段之间是不同的。
在第二个代码段 (cons 1 2)
中,它是两个数字。避免对表现效率的任何倾向,只对概念的正确性感兴趣,我们将其视为创造
---------
| * | * |
---------
| |
v v
1 2
第一个片段 (cons 1 '(2))
使用数字 1
和由 '(2)
创建的对象:
---------
| * | * |
---------
| |
v v
1 ---------
| * | * |
---------
| |
v v
2 NIL
,
您需要了解如何在 Scheme 中定义适当的列表。正确的列表是通过 cons
元素创建的,其中 cdr
部分是另一个 cons
单元格或空列表 '()
。问题中的第一个示例是一个正确的列表:
(cons 1 '(2))
(cons 1 (cons 2 '())) ; this is the same as above
=> '(1 2)
当然,我们也可以创建不遵循规则的任意 cons
单元格。问题中的第二个示例说明了这一点,它是一个 cons
单元格,其中 cdr
部分是 not 另一个 cons
单元格或空列表,因此它不是正确列表:
(cons 1 2)
=> '(1 . 2)
,
正确的列表总是以 NIL 结束。即,第一个代码示例生成两个 cons-cell,一个在另一个中,最里面的一个是 nil 终止的。然而,第二个示例不遵循标准列表的规则,因为它只是一个具有两个非 nil 值的单个 cons-cell。
(cons 1 '(2))
CLISP> (1 2) ; This list is actually (cons 1 (cons 2 NIL))
(cons 1 (cons 2 NIL))
CLISP> (1 2) ; Same as above
但是,如果您忽略 NIL,REPL 将用一个点表示。
(cons 1 2) ; this cons-cell is not terminated by NIL
CLISP> (1 . 2)
(cons 1 (cons 2 (cons 3 4))) ; A longer example
CLISP> (1 2 3 . 4) ; Notice the dot to indicate last element is non-nil.