Вы должны думать о списках в терминах минусов. Когда вы определяете список 1 и список 2, это выглядит так:
(defparameter *list-1* (cons 1 (cons 2 nil)))
(defparameter *list-2* (cons 2 (cons 3 nil)))
Затем, когда вы добавляете:
(defparameter *list-3* (cons 1 (cons 2 *list-2*)))
По сути, конс-ячейка состоит из двух частей; значение (автомобиль) и указатель (CDR). Функция «Добавить» определена так, чтобы не изменять первый список, поэтому он копируется, но затем изменяется последний cdr (обычно ноль), чтобы он указывал на второй список, а не на копию второго списка. Если бы вы хотели уничтожить первый список, вы бы использовали nconc.
Попробуйте это:
(defparameter *list-3* (nconc *list-1* *list-2*))
Затем обратите внимание на значение *list-1*
, оно равно (1 2 2 3), как *list-3*
.
Общее правило состоит в том, что неразрушающие функции (append
) не будут уничтожать существующие данные, в то время как деструктивные функции (nconc
) будут уничтожать. Однако то, что делает будущая деструктивная функция ((setf cdr)
), не является обязанностью первой неразрушающей функции.