Common Lisp: Добавление вложенного списка эффективно - PullRequest
6 голосов
/ 14 декабря 2011

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

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

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

Я уже читал, что использование векторов вместо списков может помочь, поскольку вы получаете доступ к элементам без слишком большого штрафа: Заменить элемент в списке в 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))))

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

1 Ответ

3 голосов
/ 15 декабря 2011

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

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

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

(defmacro push-to-end (item place)
  `(setf ,place (nconc ,place (list ,item))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...