Получение элемента из списка ассоциаций в lisp (elisp) - PullRequest
5 голосов
/ 13 августа 2010

Я ищу способ «вытолкнуть» элемент из списка ассоциаций, другими словами, «разрушительную» ассоциацию:

(setq alist '((a . 1) (b . 2))
(assoc-pop 'a alist) ;; -> (a . 1)
;; alist -> ((b . 2))

Есть ли какая-либо функция в жгуте elisp?Какой самый элегантный способ получить симилар функциональность?(не уверен, что подобный «побочный эффект» является хорошей практикой, даже если это возможно!)

Ответы [ 2 ]

3 голосов
/ 13 августа 2010

Нет такого встроенного оператора, о котором я знаю, но я думаю, что вы можете получить эту функцию довольно быстро:

(defmacro assoc-pop (key alist)
  `(let ((result (assoc ,key ,alist)))
     (setq ,alist (delete result ,alist))
     result))
1 голос
/ 13 августа 2010

assq-delete-all близко к тому, что вы хотите.Он ищет элементы по идентификатору объекта (eq), а не по равенству значений (equal).Он удаляет все совпадающие элементы, а не только первый.Возвращает измененный список.Вы можете адаптировать код этой функции, чтобы делать то, что вы хотите.(Но если вы собираетесь вызывать assoc-pop в цикле, а все ваши ключи являются символами, assq-delete-all делает все, что вам нужно.)

Обратите внимание, что "a" и 'a - это совершенно разные объекты.: первая строка, вторая символ.Таким образом, ваша вторая строка должна была быть (assoc-pop 'a alist).

Но на самом деле вызов (assoc-pop 'a alist) не может работать (если assoc-pop не макрос), потому что он неспособен удалить первый элемент всписок.Вы можете создать функцию, которая принимает символ в качестве аргумента и изменяет список, являющийся значением символа, следуя модели add-to-list.Вы бы назвали это как (assoc-pop 'a 'alist).

...