Spec-Zone.ru › Elisp

Списки ассоциаций

Список ассоциаций, или alist вкратце, записывает отображение ключей на значения. Это список ячеек cons, называемых ассоциациями: CAR каждой ячейки cons является ключом, а CDR — соответствующим значением.6

Вот пример alist. Ключ pine сопоставлен со значением cones; ключ oak сопоставлен со значением acorns; а ключ maple сопоставлен со значением seeds.

((pine . cones)
 (oak . acorns)
 (maple . seeds))

И значения, и ключи в alist могут быть любыми объектами Lisp. Например, в следующем alist символ a сопоставлен с числом 1, а строка "b" — со списком (2 3), который является CDR элемента alist:

((a . 1) ("b" 2 3))

Иногда лучше спроектировать alist так, чтобы сопоставленное значение хранилось в CAR CDR элемента. Вот пример такого alist:

((rose red) (lily white) (buttercup yellow))

Здесь мы рассматриваем red как значение, связанное с rose. Одно из преимуществ такого типа alist заключается в том, что вы можете хранить другую связанную информацию — даже список других элементов — в CDR CDR. Недостаток заключается в том, что вы не можете использовать rassq (см. ниже), чтобы найти элемент, содержащий данное значение. Когда ни один из этих соображений не важен, выбор является вопросом вкуса, до тех пор, пока вы сохраняете согласованность в отношении этого для любого данного alist.

Тот же самый alist, показанный выше, можно рассматривать как содержащий связанное значение в CDR элемента; значение, связанное с rose, было бы списком (red).

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

В Emacs Lisp, это не ошибка, если элемент списка ассоциаций не является ячейкой cons. Функции поиска alist просто игнорируют такие элементы. Во многих других версиях Lisp в таких случаях генерируются ошибки.

Обратите внимание, что списки свойств похожи на списки ассоциаций по нескольким аспектам. Список свойств ведет себя как список ассоциаций, в котором каждый ключ может встречаться только один раз. См. Списки свойств для сравнения списков свойств и списков ассоциаций.

Функция: assoc ключ alist &optional testfn

Эта функция возвращает первую ассоциацию для ключ в alist, сравнивая ключ с элементами alist, используя testfn, если это функция, и equal в противном случае (см. Предикаты равенства). Если testfn является функцией, она вызывается с двумя аргументами: CAR элемента из alist и ключ. Функция возвращает nil , если ни одна ассоциация в alist не имеет CAR, равного ключ в соответствии с testfn. Например:

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     ⇒ ((pine . cones) (oak . acorns) (maple . seeds))
(assoc 'oak trees)
     ⇒ (oak . acorns)
(cdr (assoc 'oak trees))
     ⇒ acorns
(assoc 'birch trees)
     ⇒ nil

Вот другой пример, в котором ключи и значения не являются символами:

(setq needles-per-cluster
      '((2 "Austrian Pine" "Red Pine")
        (3 "Pitch Pine")
        (5 "White Pine")))

(cdr (assoc 3 needles-per-cluster))
     ⇒ ("Pitch Pine")
(cdr (assoc 2 needles-per-cluster))
     ⇒ ("Austrian Pine" "Red Pine")

Функция assoc-string очень похожа на assoc за исключением того, что она игнорирует некоторые различия между строками. См. Сравнение текстов.

Функция: rassoc значение alist

Эта функция возвращает первую ассоциацию со значением значение в alist. Она возвращает nil , если ни одна ассоциация в alist не имеет CDR equal значение.

rassoc похожа на assoc , за исключением того, что она сравнивает CDR каждой ассоциации alist вместо CAR. Вы можете рассматривать это как обратную assoc, нахождение ключа для данного значения.

Функция: assq ключ alist

Эта функция похожа на assoc в том, что она возвращает первую ассоциацию для ключ в alist, но выполняет сравнение, используя eq. assq возвращает nil , если ни одна ассоциация в alist не имеет CAR eq ключ. Эта функция используется чаще, чем assoc, так как eq быстрее, чем equal, и большинство alist используют символы в качестве ключей. См. Предикаты равенства.

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
     ⇒ ((pine . cones) (oak . acorns) (maple . seeds))
(assq 'pine trees)
     ⇒ (pine . cones)

С другой стороны, assq обычно не полезна в alist, где ключи могут быть не символами:

(setq leaves
      '(("simple leaves" . oak)
        ("compound leaves" . horsechestnut)))

(assq "simple leaves" leaves)
     ⇒ Unspecified; might be nil or ("simple leaves" . oak).
(assoc "simple leaves" leaves)
     ⇒ ("simple leaves" . oak)
Функция: alist-get ключ alist &optional default remove testfn

Эта функция похожа на assq. Она находит первую ассоциацию (key . value) , сравнивая ключ с элементами alist, и, если найдена, возвращает значение этой ассоциации. Если ассоциация не найдена, функция возвращает default. Сравнение ключ с элементами alist использует функцию, указанную в testfn, по умолчанию eq.

Это обобщенная переменная (см. Обобщенные переменные), которая может быть использована для изменения значения с setf. При ее использовании для установки значения, необязательный аргумент remove не-nil означает удаление ассоциации ключ из alist, если новое значение отличается от eql default.

Функция: rassq значение alist

Эта функция возвращает первую ассоциацию со значением значение в alist. Она возвращает nil , если ни одна ассоциация в alist не имеет CDR eq значение.

rassq похожа на assq , за исключением того, что она сравнивает CDR каждой ассоциации alist вместо CAR. Вы можете рассматривать это как обратную assq, нахождение ключа для данного значения.

Например:

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))

(rassq 'acorns trees)
     ⇒ (oak . acorns)
(rassq 'spores trees)
     ⇒ nil

rassq не может искать значение, сохранённое в CAR CDR элемента:

(setq colors '((rose red) (lily white) (buttercup yellow)))

(rassq 'white colors)
     ⇒ nil

В этом случае CDR ассоциации (lily white) не является символом white, а списком (white). Это становится более понятным, если ассоциация записана в обозначении пар с точкой:

(lily white) ≡ (lily . (white))
Функция: assoc-default ключ alist &optional test default

Эта функция ищет в alist совпадение для ключ. Для каждого элемента alist она сравнивает элемент (если он атом) или CAR элемента (если он cons) с ключ, вызывая test с двумя аргументами: элементом или его CAR и ключ. Аргументы передаются в таком порядке, чтобы вы могли получить полезные результаты, используя string-match со списком ассоциаций, который содержит регулярные выражения (см. Поиск с помощью регулярных выражений). Если test опущено или nil, для сравнения используется equal.

Если элемент alist соответствует ключ по этому критерию, то assoc-default возвращает значение, основанное на этом элементе. Если элемент является cons, то значением является CDR элемента. В противном случае возвращаемое значение — default.

Если ни один элемент alist не соответствует ключ, assoc-default возвращает nil.

Функция: copy-alist alist

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

(setq needles-per-cluster
      '((2 . ("Austrian Pine" "Red Pine"))
        (3 . ("Pitch Pine"))
        (5 . ("White Pine"))))
⇒
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(setq copy (copy-alist needles-per-cluster))
⇒
((2 "Austrian Pine" "Red Pine")
 (3 "Pitch Pine")
 (5 "White Pine"))

(eq needles-per-cluster copy)
     ⇒ nil
(equal needles-per-cluster copy)
     ⇒ t
(eq (car needles-per-cluster) (car copy))
     ⇒ nil
(cdr (car (cdr needles-per-cluster)))
     ⇒ ("Pitch Pine")
(eq (cdr (car (cdr needles-per-cluster)))
    (cdr (car (cdr copy))))
     ⇒ t

Этот пример показывает, как copy-alist позволяет изменить ассоциации одной копии без влияния на другую:

(setcdr (assq 3 copy) '("Martian Vacuum Pine"))
(cdr (assq 3 needles-per-cluster))
     ⇒ ("Pitch Pine")
Функция: assq-delete-all ключ alist

Эта функция удаляет из alist все элементы, чья CAR соответствует ключ, так же, как если бы вы использовали delq для удаления каждого такого элемента по одному. Она возвращает укороченный alist и часто изменяет исходную структуру списка alist. Для получения правильных результатов используйте возвращаемое значение assq-delete-all вместо просмотра сохраненного значения alist.

(setq alist (list '(foo 1) '(bar 2) '(foo 3) '(lose 4)))
     ⇒ ((foo 1) (bar 2) (foo 3) (lose 4))
(assq-delete-all 'foo alist)
     ⇒ ((bar 2) (lose 4))
alist
     ⇒ ((foo 1) (bar 2) (lose 4))
Функция: assoc-delete-all ключ alist &optional test

Эта функция похожа на assq-delete-all , за исключением того, что принимает необязательный аргумент test — предикатную функцию для сравнения ключей в alist. Если опущено или nil, по умолчанию используется equal. Как и assq-delete-all, эта функция часто изменяет исходную структуру списка alist.

Функция: rassq-delete-all значение alist

Эта функция удаляет из alist все элементы, чья CDR соответствует значение. Она возвращает укороченный alist и часто изменяет исходную структуру списка alist. rassq-delete-all похожа на assq-delete-all , за исключением того, что она сравнивает CDR каждой ассоциации alist вместо CAR.

END_OF_DOCUMENT_MARKER ```
Макрос: let-alist alist body

Создаёт привязку для каждого символа, используемого в качестве ключей в списке ассоциаций alist, с префиксом точки. Это может быть полезно при доступе к нескольким элементам в одном и том же списке ассоциаций, и лучше всего понять его на простом примере:

(setq colors '((rose . red) (lily . white) (buttercup . yellow)))
(let-alist colors
  (if (eq .rose 'red)
      .lily))
     ⇒ white

Тело body проверяется во время компиляции, и только символы, которые появляются в body с символом «.» в качестве первого символа имени символа, будут привязаны. Поиск ключей выполняется с помощью assq, а cdr значения возвращаемого результата этой assq присваивается в качестве значения для привязки.

Вложенные списки ассоциаций поддерживаются:

(setq colors '((rose . red) (lily (belladonna . yellow) (brindisi . pink))))
(let-alist colors
  (if (eq .rose 'red)
      .lily.belladonna))
     ⇒ yellow

Вложение let-alist друг в друга разрешено, но код во внутреннем let-alist не может получить доступ к переменным, связанным внешним let-alist.

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

Spec-Zone.ru

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