dan*_*lei 10

它们并不完全相同,即使它们在REPL中评估相同的值.考虑这些例子,其中破坏性细胞被破坏性地修改:

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)
Run Code Online (Sandbox Code Playgroud)

与此相比:

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)
Run Code Online (Sandbox Code Playgroud)

在第一个版本中,您正在更改代码本身中的文字缺点单元格(因此,这是自修改代码).在第二个版本中,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
Run Code Online (Sandbox Code Playgroud)

因为这在使用破坏性操作时会导致细微的错误,所以应该在代码中小心这些文字对象.这也会影响列表文字('(1 2 3)vs. (list 1 2 3)),它们是由cons单元格构建的.

来自HyperSpec:

文字的 (对象的)直接在程序中引用而不是由程序计算; 也就是说,在报价表单中显示为数据,或者,如果对象是自我评估对象,则显示为不带引号的数据.``在形式(cons"one"'("two"))中,表达式"one",("two")和"two"是文字对象.