Они не совсем одинаковы, даже если они имеют одинаковые значения в 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)
В первой версии вы изменяете литерал 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
Поскольку это может привести к незначительным ошибкам при использовании деструктивных операций, следует быть осторожным с такими литеральными объектами в коде. Это также влияет на литералы списка ('(1 2 3)
против (list 1 2 3)
), которые построены из cons-ячеек.
Из HyperSpec :
буквально прил. (объекта) ссылается непосредственно в программе, а
чем рассчитывается программой; то есть появляются как данные в
форма цитаты, или, если объект является самооценочным объектом, появляется
в качестве данных без кавычек. `` В форме (cons "one" '("two")), выражения
«one», («two») и «two» являются буквальными объектами. ''