2011-12-14 31 views
6

Tôi đang sử dụng một plist lồng nhau để tạo ra một cấu trúc của các đối tượng (kiểu CLOS), truyền các phần tử lồng vào các phần của nó. Tôi muốn nối thêm plist lồng nhau theo cách lặp lại, nhưng do đó tôi muốn làm điều đó một cách hiệu quả về mặt thời gian và trí nhớ.Common Lisp: Gắn thêm một plist lồng nhau hiệu quả

Ví dụ dưới đây cho thấy vùng đồng bằng do một lặp:

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

vào

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

Tôi đã đọc rằng việc sử dụng vector thay vì danh sách có thể giúp đỡ, khi bạn truy cập vào các yếu tố mà không có quá nhiều hình phạt: Replace an item in a list in Common Lisp?. Tuy nhiên, tôi thực sự muốn bỏ qua việc sử dụng các vectơ.

Hơn nữa, tôi nghĩ việc sử dụng chức năng phá hoại sẽ tiết kiệm bộ nhớ và hy vọng thời gian tính toán.

Đây là cách tôi đã giải quyết nó ngay bây giờ, nhưng tôi có cảm giác rằng nó không thanh lịch và hiệu quả. Hàm fill được sử dụng để phá hủy.

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

Tôi rất mong nhận được câu trả lời của bạn.

Trả lời

3

Làm thế nào về điều này?

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

Push-to-end là một macro thường được xác định đó không phải là một phần của tiêu chuẩn lisp chung:

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