Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common Lisp: Appending a nested plist efficiently

I am using a nested plist in order to create a structure of objects (CLOS type), passing on the nested ones to its parts. I want to append the nested plist in an iterative way, but therefore I want to do it efficiently in terms of time and memory.

The below example shows the delta due to one iteration:

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

into

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

I already read that the use of vectors instead of lists might help, as you access elements without too much penalty: Replace an item in a list in Common Lisp?. However, I would really like to bypass the use of vectors.

Furthermore, I think the use a destructive function would save memory and hopefully calculation time.

This is how I solved it now at the moment, but I have the feeling that it is not elegant and efficient. The function fill is used for destructiveness.

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

I am looking forward to your answers.

like image 897
quartus Avatar asked Dec 14 '11 13:12

quartus


1 Answers

How about this?

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

Push-to-end is a commonly-defined macro that's not part of the common lisp standard:

(defmacro push-to-end (item place)
  `(setf ,place (nconc ,place (list ,item))))
like image 147
Clayton Stanley Avatar answered Oct 01 '22 06:10

Clayton Stanley