2014-06-22 6 views
8

In Emacs lisp c'è add-to-list per aggiungere un singolo elemento a un elenco (se non esiste già).Come aggiungere più elementi a un elenco in Emacs lisp

Invece di uno, voglio aggiungere più elementi. Inoltre, non voglio filtrare gli elementi duplicati ma aggiungerli comunque alla lista.

Attualmente, ho implementato la seguente funzione:

(defun append-to-list (list-var elements) 
    "Append ELEMENTS to the end of LIST-VAR. 

The return value is the new value of LIST-VAR." 
    (set list-var (append (symbol-value list-var) elements))) 

La funzione fa quello che voglio, ma mi chiedevo se qualcosa di simile (o superiore) esiste già in Emacs Lisp. Non voglio reinventare la ruota.

Aggiornamento 1: Stefan sottolinea che questo codice non funziona con lo scope lessicale. C'è un modo per farlo funzionare?

Aggiornamento 2: In precedenza ho pensato che il filtro duplicato sarebbe andato bene ma non lo è. Ho bisogno dei duplicati.

+1

Il codice va bene. Non esiste una funzione di sistema simile. – sds

+1

Non lo descriverei come "buono", ma sì, funzionerà. Usare 'symbol-value' e' set' significa che non può essere usato con una variabile con scope lessicale. A meno che tu non ** ne abbia davvero bisogno, meglio aggiungere 'elements' all'inizio, poiché' elements' sarà quasi sempre più corto (e talvolta * molto * più breve) di 'list-var'. – Stefan

+0

C'è un modo per far funzionare il codice con scope lessicale? –

risposta

4

Questo sarebbe quasi equivalente ma più veloce, in quanto non fa una copia della lista originale prima di accodare i nuovi elementi.

(defun append-to-list (list-var elements) 
    "Append ELEMENTS to the end of LIST-VAR. 

The return value is the new value of LIST-VAR." 
    (unless (consp elements) 
    (error "ELEMENTS must be a list")) 
    (let ((list (symbol-value list-var))) 
    (if list 
     (setcdr (last list) elements) 
     (set list-var elements))) 
    (symbol-value list-var)) 

append non copia l'elemento finale, ma utilizza direttamente come la coda della nuova lista, in modo che parte è identica. Tuttavia, se esistono ulteriori riferimenti all'oggetto list originale (o parte di esso), allora lo sarà una differenza funzionale tra la copia di quell'elenco (tramite append) e l'estensione (con setcdr). Quale di quei due risultati che vuoi veramente dipende da te, ovviamente.

+0

Crolla se la lista originale è nulla! – Stefan

+0

D'oh. Fisso. Grazie Stefan. – phils

+0

Almeno nel mio attuale caso d'uso non mantengo riferimenti in giro. Quindi mi sembra più pulito perché evita di copiare. Grazie! Ma può essere fatto per funzionare con scope lessicale? –

2

Se non si cura di ordinazione:

(setf var (cl-list* elt1 elt2 elt3 var)) 

L'ultimo argomento list* diventa la coda della lista risultante.

+0

Ho bisogno di controllare l'ordine, quindi non funzionerà. –

4

Ho il seguente nel mio file di init che consente di aggiungere più elementi. Non so quanto sia efficiente passare in rassegna gli elementi da aggiungere ma impedisce gli elementi duplicati.

(defun jlp/add-to-list-multiple (list to-add) 
    "Adds multiple items to LIST. 
Allows for adding a sequence of items to the same list, rather 
than having to call `add-to-list' multiple times." 
    (interactive) 
    (dolist (item to-add) 
    (add-to-list list item))) 
+0

Questo non funzionerà perché in realtà ho bisogno di valori duplicati nella lista. –