2010-08-13 10 views
5

Szukam sposobu na „Pop” elementu z listy stowarzyszenia, innymi słowy „destrukcyjny” assoc:Popping element z listy Stowarzyszenia w Lisp (elisp)

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

Are czy istnieje jakakolwiek funkcja w uprzęży eliptycznej? Jaki jest najbardziej elegancki sposób uzyskania funkcjonalności Symilar? (nie jestem pewien, że ten rodzaj "efektu ubocznego" jest dobrą praktyką, nawet jeśli jest to możliwe!)

Odpowiedz

3

Nie ma takiej wbudowanej operator, że jestem świadomy, ale myślę, że można uzyskać tę funkcjonalność dość szybko:

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

assq-delete-all jest zbliżony do tego, co chcesz. Wyszukuje elementy według tożsamości obiektów (eq), a nie według wartości (equal). Usuwa wszystkie pasujące elementy, nie tylko pierwsze. Zwraca zmodyfikowaną listę. Możesz dostosować kod tej funkcji, aby robić to, co chcesz. (Ale jeśli jechaliśmy zadzwonić assoc-pop w pętli, a wszystkie przyciski są symbolami, assq-delete-all robi wszystko, czego potrzebujemy.)

Zauważ, że "a" i 'a są zupełnie różne obiekty: pierwszy jest ciągiem, drugi symbol. Twoja druga linia powinna więc być (assoc-pop 'a alist).

Ale w rzeczywistości połączenie (assoc-pop 'a alist) nie działa (chyba że assoc-pop jest makrem), ponieważ nie jest w stanie usunąć pierwszego elementu z listy. Możesz utworzyć funkcję, która przyjmuje symbol jako argument i modyfikuje listę, która jest wartością symbolu, zgodnie z modelem add-to-list. Nazwałbyś to jako (assoc-pop 'a 'alist).

+0

Dziękuję również za punkt o symbolach, jestem nowy seplenić i jeszcze nie uchwyciłem rzeczy symbol/list/other_things. Naprawię błąd! – pygabriel