I am learning to structure my CL programm and now having trouble to use the CLOS while programming in the large with packages.
package.lisp
(defpackage :my-project.a
(:use :cl)
(:export
create-my-object
my-object
; EXPORT SINGLE SLOTS?
my-slot-1
; my-slot-...
; my-slot-n
; OR EXPORT ALL ACCESSOR-FUNCTIONS?
my-slot-1-accessor
; my-slot-n-accessor...
))
(defpackage :my-project.b
(:use :cl :my-project.a)
(:export print-object-slot))
src.lisp
While the class MY-OBJECT is defined in MY-PROJECT.A
(in-package :my-project.a)
(defclass my-object ()
((my-slot-1 :accessor my-slot-1-accessor :initarg :my-slot-1)
;... more slots
; (my-slot-2 :accessor my-slot-2-accessor :initarg :my-slot-2)
; (my-slot-n :accessor my-slot-n-accessor :initarg :my-slot-n)
))
as some CREATOR function for the objects
(defun create-my-object ()
(make-instance 'my-object
:my-slot-1 "string"
;; further slots...
))
Having some function e.g. PRINT-OBJECT in the package MY-PROJECT.B, which should handle the object instanciated from a function
(in-package :my-project.b)
(defun print-object-slot (slot-name object)
(format nil "slot-value: ~a" (SLOT-VALUE object slot-name)))
Problem
While executing following code doesn't work
(in-package :my-project.b)
(describe 'my-object) ; works
(print-object-slot
'my-slot-1 ; while this works: 'my-project.a:my-slot-1 [if slot is exported]
(create-my-object))
;; ==> slot MY-PROJECT.B:MY-SLOT-1 is missing from the object
;; MY-PROJECT.A:MY-OBJECT
To access my slots programmatically, in this situation I would need to merge the originating package-name with the slot-name, to get/setf the slot from external classes...
My understanding
The accessor-functions from CLOS objects are generic functions, belonging to the package, where they have been defined via DEFCLASS, in this case: MY-PROJECT.A
By (use-package :my-project.a)
in MY-PROJECT.B, the exported symbols are imported, that's why DESCRIBE works. But the symbols of the generic-slot-accessor-functions aren't included.
Consideration: The architecture of the programm should NOT be planned to share/export objects and slot-access. It's not well designed to bulk-import/export slots/accessor-functions.
Consideration: You can build a custom function, which get/sets the slots via the slot-accessor-function inside their package, so there is just one interface function to export?
My question:
This way handling external CLOS objects doesnt seem to be the way to go. How to export/import those accessor-functions in a sane way, without listing manually every single slot?
Edit/Solution
My terminolgy and use of slots vs. accessor-functions is a cause of this problem (thank you so much @RainerJoswig for clearing terminology up).
I did'nt use an exported version of MY-SLOT-1-ACCESSOR function, which would work as expected, but would need my to "bulk-export" them, if I would like to have access all slots in every other external package. @sds did a great job to show how to do this, and also at pointing out the general problem of my approach. Many thanks :)
In my mind, I wished to export just the object and gain full access to all the internal functions. But that's the wrong way for CLOS, since symbols and methods don't share direct bindings to the class/object, and I have to adapt better organisation of code.