Trong Lisp thông thường, cấu trúc được cho là hồ sơ cứng và cấp thấp. Họ không có tính năng năng động ưa thích.
Việc bạn có thể làm với cấu trúc là xác định loại cấu trúc mới kế thừa từ cấu trúc khác. Có duy nhất thừa kế có sẵn.
Để xử lý khả năng mở rộng động, cách thông thường là thêm khe danh sách thuộc tính vào cấu trúc. Xem câu trả lời của Joshua.
Sau đó, có Hệ thống đối tượng chung Lisp, cung cấp nhiều thừa kế và bạn có thể thay đổi các lớp khi chạy. Vì vậy, bạn có thể thêm một khe vào một lớp và các cá thể của bản cập nhật lớp đó. Bạn cũng có thể thay đổi lớp của đối tượng và vị trí có thể bị thêm hoặc xóa. Tuy nhiên, thông thường tất cả các phiên bản của một lớp sẽ có cùng một tập hợp các vị trí. Một lần nữa, người ta thấy rằng một khe với một danh sách tài sản có thể được thêm vào và sử dụng cho khả năng mở rộng.
Có các hệ thống đối tượng khác cho Common Lisp, có thể dễ dàng thêm các vị trí trên cơ sở từng trường hợp. Nhưng nó thường là quá nhiều để sử dụng chúng chỉ vì điều đó, vì chúng khá mạnh hơn một chút.
Với CLOS và giao thức Siêu đối tượng, người dùng có thể cố gắng ẩn nó.Ở đây tôi đang sử dụng LispWorks:
Chúng ta định nghĩa một lớp mixin đối với tài sản của chúng tôi:
(defclass property-mixin()
((plist :initform nil))
#+lispworks
(:optimize-slot-access nil))
Setting và đọc các thuộc tính:
(defmethod set-property ((object property-mixin) key value)
(setf (getf (slot-value object 'plist) key) value))
(defmethod get-property ((object property-mixin) key)
(getf (slot-value object 'plist) key))
Bây giờ chúng ta viết phương pháp để làm cho SLOT-VALUE
chấp nhận tên thuộc tính của chúng tôi :
(defmethod (setf clos:slot-value-using-class)
(value (class standard-class) (object property-mixin) slot-name)
(declare (ignorable class))
(if (slot-exists-p object slot-name)
(call-next-method)
(progn
(set-property object slot-name value)
value)))
(defmethod clos:slot-value-using-class ((class standard-class)
(object property-mixin)
slot-name)
(declare (ignorable class))
(if (slot-exists-p object slot-name)
(call-next-method)
(get-property object slot-name)))
Ví dụ. Chúng ta định nghĩa một lớp ô tô với hai khe:
(defclass automobile (property-mixin)
((company :initarg :company)
(motor :initarg :motor))
#+lispworks
(:optimize-slot-access nil))
Bây giờ một ví dụ:
CL-USER 45 > (setf a6 (make-instance 'automobile :company :audi :motor :v6))
#<AUTOMOBILE 402005B47B>
Chúng tôi có thể nhận được một giá trị khe bình thường:
CL-USER 46 > (slot-value c1 'motor)
:V6
Hãy viết thư cho một khe cắm mà không làm tồn tại, nhưng sẽ được thêm vào danh sách tài sản của chúng tôi:
CL-USER 47 > (setf (slot-value a6 'seats) 4)
4
Chúng ta có thể nhận được giá trị trở lại:
CL-USER 48 > (slot-value c1 'seats)
4
Cảm ơn, đây gần như chính xác những gì tôi đang tìm kiếm. Nhưng có cách nào để có danh sách thuộc tính, khi bạn đặt nó, giống như các khe khác trong 'nút'? Nói cách khác, có cách nào để làm '(make-node 'some-label: một 1: hai 2) => (MỘT SỐ NHÃN: MỘT: HAI 2)', thay vì '(MỘT SỐ NHÃN HIỆU (: ONE 1: HAI 2)) '? –
Tóm lại, không. [Câu trả lời của Rainer] (http://stackoverflow.com/a/17556349/1281433) đi sâu hơn về cấu trúc nói chung, nhưng vấn đề là cấu trúc có số khe cố định. Mặc dù bạn có thể sử dụng 'defstruct' để tạo ra" bản ghi của người nghèo "với tùy chọn' (: list list) ', bạn vẫn chỉ có một số khe cố định (có nghĩa là danh sách có một số cố định yếu tố). Nó thực sự có vẻ như bạn chỉ muốn một danh sách tài sản. –
Vâng, đọc qua câu trả lời của Rainer, tôi nghĩ rằng đó là hỏa lực nhiều hơn tôi cần cho những gì tôi đang làm. Cám ơn những lời khuyên của bạn! –