2011-12-14 2 views
6

Я использую вложенный plist, чтобы создать структуру объектов (тип CLOS), передавая вложенные части своим частям. Я хочу добавить вложенные plist итеративным способом, но поэтому я хочу сделать это эффективно с точки зрения времени и памяти.Common Lisp: Эффективное добавление вложенного plist

Ниже приведен пример дельта из-за одной итерации:

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

в

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

я уже читал, что использование векторов вместо списков может помочь, как вы получите доступ к элементам без слишком много штрафа: Replace an item in a list in Common Lisp?. Тем не менее, я бы очень хотел обойти использование векторов.

Кроме того, я считаю, что использование деструктивной функции спасет память и, надеюсь, время вычисления.

Вот как я решил это сейчас, но у меня такое ощущение, что оно не изящно и эффективно. Функция fill используется для деструктивности.

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

Я с нетерпением жду ваших ответов.

ответ

3

Как насчет этого?

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

Push-в-конец является обычно определенный макрос, который не является частью общего стандарта LISP:

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