В чем разница между
(cons 2 3)
а также
'(2 . 3)
в лиспе?
В чем разница между
(cons 2 3)
а также
'(2 . 3)
в лиспе?
'(2 . 3)
— пара точек.
(cons 2 3)
также создает точечную пару. Таким образом, они должны оценивать одно и то же.
Таким образом, один является литералом для точечной пары, другой создает точечную пару.
cons
создаст устанавливаемое место, а quote
создаст постоянное значение, которое вы не должны изменять.
- person thodg; 16.06.2017
Они не совсем одинаковы, даже несмотря на то, что они оцениваются в одни и те же значения в 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 не является буквальной. Он создается каждый раз, когда вызывается код, и будет изменена только эта свежая ячейка 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 "один" '("два")) выражения "один", ("два") и "два" являются литеральными объектами.''
literal-cons
должно соответствовать вашей реализации. На SBCL я получаю результаты как ваш non-literal-cons
. Это достаточно любопытно, поэтому я открыл новый вопрос об этом: stackoverflow.com/questions/20342793/
- person johnbakers; 03.12.2013
Оба являются объектами с похожей структурой. То есть обе они являются cons-клетками, 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)
Довольно много реализаций вернут '(3 . 3) '(4 . 3) и так далее, пока вы продолжаете вызывать b.
(1 . 2)
— это синтаксис s-выражения для ячейки cons
. Ячейка cons имеет 1 как car
и 2 как cdr
.
'(1 . 2)
с символом кавычки впереди — это сокращенное обозначение (quote (1 . 2))
. quote
инструктирует оценщика не (!) оценивать прилагаемую форму и просто вернуть ее как есть. Значение этой формы в кавычках — это сама форма. quote
говорит: не оценивай. В Common Lisp это можно рассматривать как константные литеральные данные.
(cons 1 2)
— это форма Лиспа, которая имеет функцию cons
впереди и два аргумента: 1 и 2. Если мы вычислим эту форму, функция cons
будет вызвана с аргументом 1 и 2. cons
по определению возвращает новую cons-ячейку с ее аргументами как car
и cdr
. Таким образом, (cons 1 2)
возвращает свежую новую ячейку cons, когда мы ее оцениваем.
они не одинаковые и одинаковые.
кавычка (') — это функция, которая говорит: «создать этот список, не оценивая это». пример: '(* 2 2 ) ; Он создаст список ( * 2 2 ) (список (* 2 2) ; Он создаст (4), потому что список оценивается.
функция cons создает связанные пары и только это. Пример: (cons (a b c) (1 2 3) ); создать (ab c . 1 2 3) (cons a (1 2 3 4) ) ; создать (a. 1 2 3 4)
Две функции, которые вы использовали, делают одно и то же в этом случае, но используют разные способы. потому что цитата (') просто создает список перед кавычкой символа ('), а функция cons просто создает связанную пару с "itens", которую вы дали функции.