Search code examples
lispcommon-lispclos

additional properties to slot definition


http://mop.lisp.se/concepts.html says:

An implementation is free to add additional properties to the canonicalized slot specification provided these are not symbols accessible in the common-lisp-user package, or exported by any package defined in the ANSI Common Lisp standard.

with example:

(defclass sst (plane)
     ((mach mag-step 2
            locator sst-mach
            locator mach-location
            :reader mach-speed
            :reader mach))
  (:metaclass faster-class)
  (another-option foo bar))

But when i try:

(defclass a () ((x my-option 123)))

SBCL compile it with error:

Invalid initialization argument: MY-OPTION in call for class

                SB-MOP:STANDARD-DIRECT-SLOT-DEFINITION>.    

[Condition of type SB-PCL::INITARG-ERROR]

So the question. How can I add additional properties (like "my-option") to the slot definition?


Solution

  • An implementation can do that. But the user can't add random properties. If a Common Lisp implementation supports the Meta-Object Protocol, one can add it via a custom Metaclass. But this means that one also needs to provide ways to compute slots, etc.

    That's advanced Lisp. The Book The Art of the Metaobject Protocol has an example in chapter 3, Extending the Language.

    A simple example (works in LispWorks):

    (defclass foo-meta-class (standard-class) ())
    
    (defclass foo-standard-direct-slot-definition (standard-direct-slot-definition)
      ((foo :initform nil :initarg :foo)))
    
    (defclass foo-standard-effective-slot-definition (standard-effective-slot-definition)
      ((foo :initform nil :initarg :foo)))
    
    (defmethod clos:direct-slot-definition-class ((class foo-meta-class) &rest initargs)
      (find-class 'foo-standard-direct-slot-definition))
    
    (defmethod clos:effective-slot-definition-class ((class foo-meta-class) &rest initargs)
      (find-class 'foo-standard-effective-slot-definition))
    

    Let's use it in an user-defined class:

    (defclass foo ()
      ((a :initarg :a :foo :bar))
      (:metaclass foo-meta-class))
    

    The slot-definition object then will have a slot foo with content bar.

    CL-USER 10 > (find-class 'foo)
    #<FOO-META-CLASS FOO 42200995AB>
    
    CL-USER 11 > (class-direct-slots *)
    (#<FOO-STANDARD-DIRECT-SLOT-DEFINITION A 42200B4C7B>)
    
    CL-USER 12 > (describe (first *))
    
    #<FOO-STANDARD-DIRECT-SLOT-DEFINITION A 42200B4C7B> is a FOO-STANDARD-DIRECT-SLOT-DEFINITION
    FOO                     :BAR
    READERS                 NIL
    WRITERS                 NIL
    NAME                    A
    INITFORM                NIL
    INITFUNCTION            NIL
    TYPE                    T
    FLAGS                   1
    INITARGS                (:A)
    ALLOCATION              :INSTANCE
    DOCUMENTATION-SLOT      NIL
    

    Obviously there is more to it, if the property should have any real meaning.