Spec-Zone.ru › Elisp

Функции перестановки списков

Ниже приведены функции, которые переставляют списки деструктивно, изменяя CDR составляющих их cons-ячеек. Эти функции деструктивны, поскольку они изменяют исходные списки, переданные им в качестве аргументов, связывая их cons-ячейки в новый список, который и возвращается.

См. delq в разделе Использование списков в качестве множеств, где описана ещё одна функция, изменяющая cons-ячейки.

Функция: nconc &rest lists

Эта функция возвращает список, содержащий все элементы из lists. В отличие от append (см. Создание cons-ячеек и списков), списки из lists не копируются. Вместо этого последний CDR каждого списка из lists изменяется так, чтобы ссылаться на следующий список. Последний список из lists не изменяется. Например:

(setq x (list 1 2 3))
     ⇒ (1 2 3)
(nconc x '(4 5))
     ⇒ (1 2 3 4 5)
x
     ⇒ (1 2 3 4 5)

Поскольку последний аргумент nconc сам по себе не изменяется, допустимо использовать константный список, например '(4 5), как в примере выше. По той же причине последний аргумент не обязательно должен быть списком:

(setq x (list 1 2 3))
     ⇒ (1 2 3)
(nconc x 'z)
     ⇒ (1 2 3 . z)
x
     ⇒ (1 2 3 . z)

Однако остальные аргументы (все, кроме последнего) должны быть изменяемыми списками. Это могут быть точечные списки, последние CDR которых затем заменяются следующим аргументом:

(nconc (cons 1 2) (cons 3 (cons 4 5)) 'z)
     ⇒ (1 3 4 . z)

Распространённая ошибка — использовать константный список в качестве не последнего аргумента nconc. Если вы так поступите, поведение программы будет неопределённым (см. Самовычисляемые формы). Программа может изменяться при каждом запуске! Вот что может произойти (хотя это не гарантируется):

(defun add-foo (x)            ; We want this function to add
  (nconc '(foo) x))           ;   foo to the front of its arg.
(symbol-function 'add-foo)
     ⇒ #f(lambda (x) [t] (nconc '(foo) x))
(setq xx (add-foo '(1 2)))    ; It seems to work.
     ⇒ (foo 1 2)
(setq xy (add-foo '(3 4)))    ; What happened?
     ⇒ (foo 1 2 3 4)
(eq xx xy)
     ⇒ t
(symbol-function 'add-foo)
     ⇒ #f(lambda (x) [t] (nconc '(foo 1 2 3 4) x))

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Rearrangement.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API