2011-12-14 8 views
6

Sto usando un plist nidificato per creare una struttura di oggetti (tipo CLOS), passando a quelli nidificati alle sue parti. Voglio aggiungere il plist annidato in modo iterativo, ma quindi voglio farlo in modo efficiente in termini di tempo e memoria.Common Lisp: Aggiunta di un plist nidificato in modo efficiente

L'esempio seguente mostra il delta a causa di un'iterazione:

'(:airframer "Boeing" :type "777" :wing-plist ((:side :left :winglet? nil) 
               (:side :right :winglet? nil))) 

in

'(:airframer "Boeing" :type "777" :wing-plist ((:type :main-wing :side :left) 
               (:type :main-wing :side :right) 
               (:type :stabilizer :size :left))) 

ho già letto che l'uso di vettori al posto delle liste potrebbe aiutare, come si accede elementi senza troppo Penalità molto: Replace an item in a list in Common Lisp?. Tuttavia, mi piacerebbe davvero aggirare l'uso dei vettori.

Inoltre, penso che l'uso di una funzione distruttiva salverebbe la memoria e, auspicabilmente, il tempo di calcolo.

Ecco come l'ho risolto ora al momento, ma ho la sensazione che non sia elegante ed efficiente. La funzione fill viene utilizzata per la distruttività.

(defun append-nested-plist (plist key sub-plist) 
    (let* ((key-pos (position key plist))) 
    (fill plist (append (getf plist key) (list sub-plist)) 
      :start (+ key-pos 1) :end (+ key-pos 2)))) 

Non vedo l'ora di ricevere le vostre risposte.

risposta

3

Che ne dici di questo?

(defun append-nested-plist (plist key sub-plist) 
    (push-to-end sub-plist (getf plist key)) 
    plist) 

Push-to-end è una macro comunemente definito che non fa parte dello standard Common Lisp:

(defmacro push-to-end (item place) 
    `(setf ,place (nconc ,place (list ,item))))