有什么区别
(cons 2 3)
Run Code Online (Sandbox Code Playgroud)
和
'(2 . 3)
Run Code Online (Sandbox Code Playgroud)
在Lisp?
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"是文字对象.