2011-12-14 11 views
6

Estoy usando un plist anidado para crear una estructura de objetos (tipo CLOS), pasando los anidados a sus partes. Quiero adjuntar el pliego anidado de forma iterativa, pero, por lo tanto, quiero hacerlo de manera eficiente en términos de tiempo y memoria.Common Lisp: Anexar un plist anidado de manera eficiente

El ejemplo de abajo muestra el delta debido a una iteración:

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

en

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

yo ya leí que el uso de vectores en lugar de las listas podría ayudar, a medida que accede elementos sin demasiado mucha penalización: Replace an item in a list in Common Lisp?. Sin embargo, realmente me gustaría pasar por alto el uso de vectores.

Además, creo que el uso de una función destructiva podría ahorrar memoria y, con suerte, tiempo de cálculo.

Así lo resolví ahora, pero tengo la sensación de que no es elegante y eficiente. La función fill se usa para la destructividad.

(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)))) 

Esperamos sus respuestas.

Respuesta

3

¿Qué tal esto?

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

Push-to-End es un macro definido comúnmente que no es parte de la norma Common Lisp:

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