【发布时间】:2011-07-28 20:18:30
【问题描述】:
有什么区别
(cons 2 3)
和
'(2 . 3)
在 Lisp 中?
【问题讨论】:
-
第二个表达式中是句号还是逗号?
-
@David:想知道是否可以更改您的答案选择。我比我更喜欢丹蕾。
有什么区别
(cons 2 3)
和
'(2 . 3)
在 Lisp 中?
【问题讨论】:
它们并不完全相同,即使它们在 REPL 中评估为相同的值。考虑以下示例,其中 cons 单元被破坏性修改:
TEST> (defun literal-cons ()
(let ((cons '(1 . 2)))
(incf (cdr cons))
cons))
LITERAL-CONS
TEST> (literal-cons)
(1 . 3)
TEST> (literal-cons)
(1 . 4)
TEST> (literal-cons)
(1 . 5)
与此相比:
TEST> (defun non-literal-cons ()
(let ((cons (cons 1 2)))
(incf (cdr cons))
cons))
NON-LITERAL-CONS
TEST> (non-literal-cons)
(1 . 3)
TEST> (non-literal-cons)
(1 . 3)
在第一个版本中,您正在更改代码本身中的literal cons 单元格(因此,这是自修改代码)。在第二个版本中,cons 单元格不是文字的。每次调用代码时都会产生它,并且只会更改这个新的 cons 单元格。
TEST> (function-lambda-expression #'literal-cons)
(LAMBDA NIL
(DECLARE (CCL::GLOBAL-FUNCTION-NAME LITERAL-CONS))
(BLOCK LITERAL-CONS (LET ((CONS '(1 . 5))) (INCF (CDR CONS)) CONS))) ;; notice the '(1 . 5)
NIL
LITERAL-CONS
由于在使用破坏性操作时这可能会导致细微的错误,因此在代码中应小心使用此类文字对象。这也会影响由 cons 单元构建的列表文字('(1 2 3) 与 (list 1 2 3))。
来自HyperSpec:
字面量词。 (对象的)在程序中直接引用,而不是 不是由程序计算的;也就是说,作为数据出现在 引用形式,或者,如果对象是自评估对象,则出现 作为未引用的数据。 ``在形式 (cons "one" '("two")) 中,表达式 "one"、("two") 和 "two" 是文字对象。''
【讨论】:
literal-cons 函数的行为必须特定于您的实现。在 SBCL 上,我得到的结果是您的 non-literal-cons。这很好奇,以至于我提出了一个新问题:stackoverflow.com/questions/20342793/…
两者都是具有相似结构的对象。也就是说,它们都是 cons cell,其中 2 个在 CAR 位置,3 个在 CDR 位置。
它们之间的主要区别在于 '(2 . 3) 是一个常数,而 (cons 2 3) 生成一个新的 cons 单元格。如果您采用以下两个(外观相似的)函数,则它们之间的区别应该会变得明显:
(defun a ()
(let ((v (cons 2 3)))
(incf (car v))
v)
(defun b ()
(let ((v '(2 . 3)))
(incf (car v))
v)
当您继续调用 b 时,相当多的实现会返回 '(3 . 3) '(4 . 3) 等等。
【讨论】:
'(2 . 3) 是一个点对。
(cons 2 3) 也会创建一个点对。所以这些应该评估为同一件事。
所以一个是一个点对的文字,另一个创建一个点对。
【讨论】:
cons 会产生一个可设置的位置,quote 会产生一个你不应该修改的常量值。
(1 . 2) 是cons 单元格的 s 表达式语法。 cons 单元格有 1 作为car 和 2 作为cdr。
'(1 . 2) 前面带有引号字符是(quote (1 . 2)) 的缩写。 quote 指示评估者不要 (!) 评估它所包含的表单并按原样返回它。这个引用表单的值就是表单本身。 quote 说:不评价。在 Common Lisp 中,这可以被认为是常量文字数据。
(cons 1 2) 是一个 Lisp 表单,它前面有函数 cons 和两个参数:1 和 2。如果我们评估这个表单,函数 cons 会被调用,参数是 1 和 2。cons根据定义返回一个新的 cons 单元格,其参数为 car 和 cdr。所以 (cons 1 2) 在我们评估它时会返回一个新的 cons 单元格。
【讨论】:
它们不一样,而且是一样的。
符号引号 (') 是一个函数,它表示:“创建此列表而不评估此列表。” 例如:'(* 2 2);它将创建列表 ( * 2 2 ) (list (* 2 2) ; 它将创建 (4) 因为列表已被评估。
函数 cons 创建关联的对,仅此而已。 示例: (cons (a b c) (1 2 3) ) ;create (a b c . 1 2 3) (cons a (1 2 3 4) ) ;创建 (a. 1 2 3 4)
您使用的两个函数在本例中执行相同的操作,但使用不同的方式执行此操作。 因为引号 (') 只是在 simbol 引号 (') 前面创建列表,而 cons 函数只是创建与您给函数的“itens”相关的对。
【讨论】: