5.5 Изменение переменных списков

Эти функции и одна макрос предоставляют удобные способы изменения списка, хранящегося в переменной.

Макрос: push element listname

Этот макрос создает новый список, чей CAR равен element, а чей CDR — список, указанный в listname, и сохраняет этот список в listname. В самом простом случае listname — это нецитируемый символ, называющий список, и этот макрос эквивалентен (setq listname (cons element listname)).

(setq l '(a b))
     ⇒ (a b)
(push 'c l)
     ⇒ (c a b)
l
     ⇒ (c a b)

Более обобщенно listname может быть обобщенной переменной. В таком случае этот макрос выполняет эквивалент (setf listname (cons element listname)). См. Обобщенные переменные.

Для макроса pop, который удаляет первый элемент из списка, см. Доступ к элементам списка.

Две функции изменяют списки, являющиеся значениями переменных.

Функция: add-to-list symbol element &optional append compare-fn

Эта функция устанавливает переменную symbol, помещая element в список, если element еще не является членом этого значения. Она возвращает результирующий список, независимо от того, был ли он обновлен. Значение symbol должно быть списком до вызова. add-to-list использует compare-fn для сравнения element с существующими членами списка; если compare-fn равно nil, используется equal.

Обычно, если element добавляется, он добавляется в начало symbol, но если необязательный аргумент append не равен nil, он добавляется в конец.

Аргумент symbol не цитируется неявно; add-to-list является обычной функцией, как set, и отличается от setq. Цитируйте аргумент самостоятельно, если хотите.

Эта функция предназначена для добавления элементов в конфигурационные переменные, такие как load-path (см. Поиск библиотек), image-load-path (см. Определение изображений) и т. д. Ее код включает довольно много специальных проверок для этих целей и выдает предупреждения в их поддержку. По этой причине мы не рекомендуем использовать ее в программах Lisp для построения произвольных списков; вместо этого используйте push. См. Изменение переменных списков.

Не используйте эту функцию, когда symbol ссылается на лексическую переменную.

Вот сценарий, показывающий, как использовать add-to-list:

(setq foo '(a b))
     ⇒ (a b)

(add-to-list 'foo 'c)     ;; Добавить c.
     ⇒ (c a b)

(add-to-list 'foo 'b)     ;; Без эффекта.
     ⇒ (c a b)

foo                       ;; foo был изменен.
     ⇒ (c a b)

Эквивалентное выражение для (add-to-list 'var value) выглядит так:

(if (member value var)
    var
  (setq var (cons value var)))
Функция: add-to-ordered-list symbol element &optional order

Эта функция устанавливает переменную symbol, вставляя element в старое значение, которое должно быть списком, в позиции, указанной order. Если element уже является членом списка, его позиция в списке корректируется в соответствии с order. Принадлежность проверяется с помощью eq. Эта функция возвращает результирующий список, независимо от того, был ли он обновлен.

Параметр order обычно является числом (целым или дробным), и элементы списка сортируются в порядке невозрастания чисел.

order также может быть опущен или равен nil. Тогда чиковый порядок element остается неизменным, если он уже имеет такой порядок; в противном случае element не имеет чикового порядка. Элементы без числового порядка списка помещаются в конец списка, без определенного порядка.

Любое другое значение для order удаляет числовой порядок element, если он уже есть; в противном случае это эквивалентно nil.

Аргумент symbol не цитируется неявно; add-to-ordered-list является обычной функцией, как set, и отличается от setq. Цитируйте аргумент самостоятельно, если необходимо.

Информация о порядке хранится в хеш-таблице в свойстве list-order переменной symbol. symbol не может ссылаться на лексическую переменную.

Вот сценарий, показывающий, как использовать add-to-ordered-list:

(setq foo '())
     ⇒ nil

(add-to-ordered-list 'foo 'a 1)     ;; Добавить a.
     ⇒ (a)

(add-to-ordered-list 'foo 'c 3)     ;; Добавить c.
     ⇒ (a c)

(add-to-ordered-list 'foo 'b 2)     ;; Добавить b.
     ⇒ (a b c)

(add-to-ordered-list 'foo 'b 4)     ;; Переместить b.
     ⇒ (a c b)

(add-to-ordered-list 'foo 'd)       ;; Добавить d.
     ⇒ (a c b d)

(add-to-ordered-list 'foo 'e)       ;; Добавить e.
     ⇒ (a c b e d)

foo                       ;; foo был изменен.
     ⇒ (a c b e d)