2010-08-13 4 views
5

Je cherche un moyen de « pop » un élément d'une liste d'association, autrement dit une assoc « destructrice »:Popping un élément d'une liste d'association en Lisp (elisp)

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

Est-ce at-il une fonction dans le harnais elisp? Quelle est la manière la plus élégante d'obtenir une fonctionnalité symilar? (pas sûr que ce genre de "effet secondaire" est une bonne pratique, même si c'est possible!)

Répondre

3

Il n'y a pas opérateur intégré que je suis au courant, mais je pense que vous pouvez obtenir cette fonctionnalité assez rapidement:

(defmacro assoc-pop (key alist) 
    `(let ((result (assoc ,key ,alist))) 
    (setq ,alist (delete result ,alist)) 
    result)) 
1

assq-delete-all est proche de ce que vous voulez. Il recherche les éléments par identité d'objet (eq), et non par égalité de valeur (equal). Il supprime tous les éléments correspondants, pas seulement le premier. Il renvoie la liste modifiée. Vous pouvez adapter le code de cette fonction pour faire ce que vous voulez. (Mais si vous allez appeler assoc-pop dans une boucle, et toutes vos clés sont des symboles, assq-delete-all fait tout dont vous avez besoin.)

Notez que "a" et 'a sont des objets complètement différents: le premier est une chaîne, le second est un symbole. Donc, votre deuxième ligne aurait dû être (assoc-pop 'a alist).

Mais en fait, l'appel (assoc-pop 'a alist) ne peut pas fonctionner (sauf si assoc-pop est une macro), car il est incapable de supprimer le premier élément d'une liste. Vous pouvez créer une fonction qui prend un symbole comme argument et modifie la liste correspondant à la valeur du symbole, en suivant le modèle de add-to-list. Vous l'appelez (assoc-pop 'a 'alist).

+0

Merci aussi pour le point sur les symboles, je suis nouveau à lisp et je n'ai pas encore saisi le symbole/liste/autres choses. Je corrige l'erreur! – pygabriel