Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>In Common Lisp, structures are thought as rigid and low-level records. They don't have fancy dynamic features.</p> <p>What you can do with structures is to defined a new structure type which inherits from another one. There is single inheritance available.</p> <p>To handle dynamic extensibility, a typical way is to add a property list slot to a structure. See the answer of Joshua.</p> <p>Then there is the Common Lisp Object System, which provides multiple inheritance and you can change classes at runtime. So you can add a slot to a class and the instances of that class update themselves. You can also change the class of an object and slots may get added or deleted. Still, typically all instances of a class will have the same set of slots. Again, one sees that a slot with a property list can be added and used for extensibility.</p> <p>There are other object systems for Common Lisp, which can easily add slots on a per-instance base. But it is usually too much to use them just for that, since they are quite a bit more powerful.</p> <p>With CLOS and the Meta-object protocol one can try to hide it. Here I am using LispWorks:</p> <p>We define a mixin class for our properties:</p> <pre><code>(defclass property-mixin () ((plist :initform nil)) #+lispworks (:optimize-slot-access nil)) </code></pre> <p>Setting and reading the properties:</p> <pre><code>(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)) </code></pre> <p>Now we write methods to make <code>SLOT-VALUE</code> accepting our property names:</p> <pre><code>(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))) </code></pre> <p>Example. We define an automobile class with two slots:</p> <pre><code>(defclass automobile (property-mixin) ((company :initarg :company) (motor :initarg :motor)) #+lispworks (:optimize-slot-access nil)) </code></pre> <p>Now an instance:</p> <pre><code>CL-USER 45 &gt; (setf a6 (make-instance 'automobile :company :audi :motor :v6)) #&lt;AUTOMOBILE 402005B47B&gt; </code></pre> <p>We can get a normal slot value:</p> <pre><code>CL-USER 46 &gt; (slot-value c1 'motor) :V6 </code></pre> <p>Let's write to a slot which does not exist, but will be added to our property list:</p> <pre><code>CL-USER 47 &gt; (setf (slot-value a6 'seats) 4) 4 </code></pre> <p>We can get the value back:</p> <pre><code>CL-USER 48 &gt; (slot-value c1 'seats) 4 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload