|
From: Hoehle, Joerg-C. <Joe...@t-...> - 2003-02-19 13:11:54
|
Hi,
I'm seeking help with CLOS. I want to define a slot that all instances =
of a class will share. This sounds like typical :allocation :class. But =
read on.
One of these special slots is supposed to contain a function (closure) =
that I want compiled at file-compilation time. Another will be set at =
run-time. Another will contain the lambda expression to compile at =
run-time and ought to be defined at file-compilation time as well.
I thought about the following macro to declare the code:
(define-analyse-line ((analyse durchsatz))
(incf (gethash key (analyse-top-table analyse)))
(princ #\; (analyse-outstream analyse)))
which would macroexpand to:
(let ((*columns-used* '()))
(setf (analyse-line-function (find-class 'durchsatz))
(lambda (analyse .line. .start-positions. .stop-positions.)
(macrolet ((log-line-universal-time () ;TODO? flet
(or (analyse-universal-time analyse) #))
(log-line-sql-time ()
(format nil #)))
body...))
(setf (analyse-used-columns #) *columns-used*)))
and here's something which cannot work
(defmacro define-analyse-line ((var class) &body body)
(let* ((*precompile* nil)
(*columns-used* '()))
(setf (analyse-line-function (find-class ',class))
(lambda (,var .line. .start-positions. .stop-positions.)
,@body))
(setf (analyse-line-lambda (find-class ',class)) ',body)
(setf (analyse-used-columns (find-class ',class)) *columns-used*)))
The reason it cannot work is that analyse-line-lambda and =
-line-function are not typically slots of (find-class 'analyse), but =
rather shared slots of each instance.
Need I got MOP here or is that overshoot? Am I misguided?
Maybe all I need is a wrapper around defclass and some initform =
instead?
This could become weird as well, since the closure body may reference =
slots to be defined in this same DEFCLASS form (e.g. analyse-top-table =
above).
Thanks for your help,
J=F6rg H=F6hle.
|
|
From: Hoehle, Joerg-C. <Joe...@t-...> - 2003-02-20 16:52:34
|
Hi,
Sam wrote:
>IIUC, you need what MOP calls a "class prototype".
>I.e.,
>(defclass foo ()
> (bar :allocation :class))
>
>(setf (slot-value (class-prototype (find-class 'foo)) 'bar)
> (lambda () ...))
>right?
Looks like this would do the job. I'll have to take the AMOP book out of the library again.
>(defun shared-slot (class slot)
> (cond ((null slot-location) (error "no such slot"))
>(setf (shared-slot (find-class 'foo) 'bar) (lambda () ...))
>Does this solve your problem?
This would so, as far as CLOS is concerned. But I ran into another, non CLOS, but compile-time problem (see other mail).
>Should we export CLOS:SHARED-SLOT, CLOS:SHARED-SLOT-BOUNDP and
>CLOS:SHARED-SLOT-MAKUNBOUND?
Why not? Once you wrote them...
Hmm, better error messages are needed, which leads to the following thought.
>An alternative would be to add a class prototype (which would waste an
>instance for each class...)
The class-prototype hack(?) may be something
1) which integrates better with the rest of CLOS. E.g. I guess one can raise a slot-missing error (which needs an instance as the second argument). How to raise slot-missing from within the proposed shared-slot function?
2) which seems to be somewhat standard in CLOS (I guess from your wording), whereas SHARED-SLOT would be specific to CLISP.
>I don't thing we may extend SLOT-VALUE and friends like this:
>(SLOT-VALUE symbol slot) == (SHARED-SLOT (find-class symbol) slot)
SLOT-VALUE is a function, so I guess there's not much to be changed there or general performance will suffer. But I don't understand this ==.
Maybe a separate weak hash-table trick may allow to implement a singleton class-prototype for all classes for which one was requested without spending an extra slot on each class?
(defvar clos:*class-prototypes* (make-hash-table :Test #'eq :weak :keys))
; weak so as not to grow unnecessarily
(defun class-prototype (class)
(check-type class 'standard-class)
(or (gethash class *class-prototypes* nil)
(setf (gethash class *class-prototypes)
(make-weird-instance-full-of #<unbound> slots except for the shared ones or whatever-is-needed))))
Or maybe that class-prototype should not be an instance of its class (but of some other one). Would that be against programmer's expectations??
Regards,
Jorg Hohle.
|
|
From: Sam S. <sd...@gn...> - 2003-02-20 19:15:18
|
> * In message <9F8...@G8...> > * On the subject of "[clisp-list] CLOS: class-wide slots defined at compile-time?" > * Sent on Thu, 20 Feb 2003 17:52:21 +0100 > * Honorable "Hoehle, Joerg-Cyril" <Joe...@t-...> writes: > > Sam wrote: > >An alternative would be to add a class prototype (which would waste an > >instance for each class...) > > The class-prototype hack(?) may be something > 2) which seems to be somewhat standard in CLOS (I guess from your > wording), whereas SHARED-SLOT would be specific to CLISP. it's in MOP. > Maybe a separate weak hash-table trick may allow to implement a > singleton class-prototype for all classes for which one was requested > without spending an extra slot on each class? > (defvar clos:*class-prototypes* (make-hash-table :Test #'eq :weak :keys)) > ; weak so as not to grow unnecessarily > (defun class-prototype (class) > (check-type class 'standard-class) > (or (gethash class *class-prototypes* nil) > (setf (gethash class *class-prototypes) > (make-weird-instance-full-of #<unbound> slots except for the shared ones or whatever-is-needed)))) > Or maybe that class-prototype should not be an instance of its class > (but of some other one). Would that be against programmer's > expectations?? it's better to keep the prototype inside the CLASS struct. class may be redefined &c. we may create the prototype on demand. -- Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html> MS DOS: Keyboard not found. Press F1 to continue. |
|
From: Hoehle, Joerg-C. <Joe...@t-...> - 2003-02-21 09:29:29
|
Hi, >> The class-prototype hack(?) may be something >> 2) which seems to be somewhat standard in CLOS (I guess from your >> wording), >it's in MOP. I found http://www.elwoodcorp.com/alu/mop/dictionary.html http://www.franz.com/support/documentation/6.2/doc/mop/dictionary.html "Generic Function class-prototype class Returns a prototype instance of class. Whether the instance is initialized is not specified. The results are undefined if a portable program modifies the binding of any slot of prototype instance." It says "any slot", not "any local slot". Therefore, modifying shared slots like I'd wish to do seems unportable as well. [English: probably needs to say "slot of *a/the/this* prototype instance". >it's better to keep the prototype inside the CLASS struct. >class may be redefined &c. >we may create the prototype on demand. considering class redefinition: forget the hash-table I suggested. Just create a new object for each invocation of class-prototype. W.r.t. redefinitions, with or without a table, the class-prototype instance may be subject to update-instance-for-redefined-class, like all other instances. So I still don't see the necessity to spend a slot for this (supposedly) seldomly used thing. The MOP does not specify that there's a unique class-prototype instance for each class. Maybe they said "consequences unspecified" because they wanted to leave it open whether this prototype would actually be considered by update-instance-for-redefined-class. Consider how user code (custom defmethod update-instance ...) may fail when encountering an instance with no initialized (bound) local slot. That might not meet the programmer's expectations. Conversely, I can't imagine how the local slots could possibly be initialized, since there's no way to obtain possibly required initargs. All in all, this same problem w.r.t. redefinitions also applies to reading slots. What about: (defun class-prototype (class) (allocate-instance class)) ;TODO class-prototype as a GF However, this is not compliant, since "This generic function signals an error if class has not been finalized" whereas allocate-instance would finalize when needed. However, allocate-instance may be all I need. Are there compiler restrictions on using defclass and make/allocate-instance in the same file? http://www.lispworks.com/reference/HyperSpec/Body/03_bbc.htm does not indicate something like this. I may need eval-when around my defclass forms. Regards, Jorg Hohle. |
|
From: Sam S. <sd...@gn...> - 2003-02-21 16:47:22
|
> * In message <9F8...@G8...> > * On the subject of "[clisp-list] CLOS: class-wide slots defined at compile-time?" > * Sent on Fri, 21 Feb 2003 10:27:34 +0100 > * Honorable "Hoehle, Joerg-Cyril" <Joe...@t-...> writes: > > Are there compiler restrictions on using defclass and > make/allocate-instance in the same file? not in CLISP. you may need to tweak pcl::*defclass-times*, pcl::*defgeneric-times* and pcl::*defmethod-times* for CMUCL and SBCL. -- Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html> Single tasking: Just Say No. |
|
From: Christophe R. <cs...@ca...> - 2003-02-21 19:50:07
|
Sam Steingold <sd...@gn...> writes: > > * In message <9F8...@G8...> > > * On the subject of "[clisp-list] CLOS: class-wide slots defined at compile-time?" > > * Sent on Fri, 21 Feb 2003 10:27:34 +0100 > > * Honorable "Hoehle, Joerg-Cyril" <Joe...@t-...> writes: > > > > Are there compiler restrictions on using defclass and > > make/allocate-instance in the same file? > > not in CLISP. > you may need to tweak pcl::*defclass-times*, pcl::*defgeneric-times* > and pcl::*defmethod-times* for CMUCL and SBCL. For what it's worth, those variables do not exist in SBCL, and as long as the class is defined before it is used there is no problem with making an instance of a class in the same file. Cheers, Christophe -- http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383 757 (set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b))) (defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambridge) |