From: Vassili Bykov
Subject: Re: Direct accessing of shared slots revisited (for CLISP)
Date: 
Message-ID: <uium2r8ri.fsf@objectpeople.com>
Pierre Mai <····@cs.tu-berlin.de> wrote:
> The 'problem' of accessing shared slots of classes without going
> through a dummy instance has been raised on this newsgroup a couple
> of times, and solutions have been given for CLOS implementations
> which implement enough parts of the MOP, like the one below:
>
> (defun class-slot-value (classname name)
>   [...]
>
> But it seems CLISP doesn't implement this part of the MOP, and now I'm 
> looking for a somewhat elegant/efficient solution for CLISP...

Here is the idea that is suggested by the CLISP CLOS implementation --
see clos.lsp, around lines 230 (untested):

(in-package :clos)
(defun class-slot-value (class-name slot-name)
  (let* ((class (find-class class-name))
	 (slot-location (gethash slot-name 
				 (class-slot-location-table class)))
	 (value (cond ((consp slot-location)
		       (svref (class-shared-slots (car slot-location))
			      (cdr slot-location)))
		      (t
		       (slot-missing class nil slot-name 'slot-value)))))
    (if (eq value unbound)
      (slot-unbound class nil slot-name)
      value)))

The suspicious thing is that the NIL in the calls to SLOT-MISSING and
SLOT-UNBOUND is supposed to be the instance for which the operation
failed; I am not sure passing a NIL is really a Good Thing to do.

--Vassili

From: Pierre Mai
Subject: Re: Direct accessing of shared slots revisited (for CLISP)
Date: 
Message-ID: <m3emwjf0ot.fsf@torus.cs.tu-berlin.de>
Vassili Bykov <·······@objectpeople.com> writes:

> Here is the idea that is suggested by the CLISP CLOS implementation --
> see clos.lsp, around lines 230 (untested):
> 
> [suggested solution snipped]

Thanks to the proposed solution, I was able to get something up and
working: The handling of #<UNBOUND> in CLISP (esp. in the interpreter)
is somewhat difficult, since this is not a real lisp value, e.g. you
cannot really bind a variable to this value.  So the code in clos.lsp
used a hack (which I still don't fully understand, to be honest) to
get clos::unbound to get the required value.

With some modification the following code now seems to work in CLISP,
_BUT ONLY IF YOU COMPILE IT_.  In the interpreter, CLISP interprets
the #<UNBOUND> to which value gets bound, as if value itself was
unbound, so you'd need the handler-case which I commented out in the
following code (whether this is really a good idea, and doesn't clash
with CLISP's internals I don't know, so beware):

(in-package :clos)

(let ((unbound (sys::%record-ref
		(allocate-std-instance <standard-object> 2) 1)))
(defun class-slot-value (class-name slot-name)
  (let* ((class (find-class class-name))
	 (slot-location (gethash slot-name 
				 (class-slot-location-table class)))
	 (value (cond ((consp slot-location)
		       (svref (class-shared-slots (car slot-location))
			      (cdr slot-location)))
		      (t
		       (slot-missing class nil slot-name 'slot-value)))))
;;    (handler-case
	(if (eq value unbound)
	    (slot-unbound class nil slot-name)
	    value)
;;      (unbound-variable () (slot-unbound class nil slot-name)))))
)))

> The suspicious thing is that the NIL in the calls to SLOT-MISSING and
> SLOT-UNBOUND is supposed to be the instance for which the operation
> failed; I am not sure passing a NIL is really a Good Thing to do.

It doesn't seem to cause any problems, but there might be hidden
problems, I'm not aware of...

> --Vassili

Thanks again for pointing me in the right direction...

Regs, Pierre.

-- 
Pierre Mai <····@cs.tu-berlin.de>	http://home.pages.de/~trillian/
  "Such is life." -- Fiona in "Four Weddings and a Funeral" (UK/1994)
From: Bruno Haible
Subject: Re: Direct accessing of shared slots revisited (for CLISP)
Date: 
Message-ID: <6mmo12$30k@news.u-bordeaux.fr>
Pierre Mai <····@cs.tu-berlin.de> wrote:
>
> With some modification the following code now seems to work in CLISP,
> _BUT ONLY IF YOU COMPILE IT_.

You can force the entire  (let ((unbound ...)) (defun ...))  to be compiled
by wrapping it in  (locally (declare (compile)) ...).

A nice hack :-)

         Bruno
From: Pierre Mai
Subject: Re: Direct accessing of shared slots revisited (for CLISP)
Date: 
Message-ID: <m3af73kd7t.fsf@torus.cs.tu-berlin.de>
······@clisp.cons.org (Bruno Haible) writes:

> You can force the entire  (let ((unbound ...)) (defun ...))  to be compiled
> by wrapping it in  (locally (declare (compile)) ...).
> 
> A nice hack :-)

Thanks, it all works nicely now... 

Regs, Pierre.

Below the complete version, for the archives:

(in-package :clos)

(locally (declare (compile))
  (let ((unbound (sys::%record-ref
		  (allocate-std-instance <standard-object> 2) 1)))
    (defun class-slot-value (class-name slot-name)
      (let* ((class (find-class class-name))
	     (slot-location (gethash slot-name 
				     (class-slot-location-table class)))
	     (value (cond ((consp slot-location)
			   (svref (class-shared-slots (car slot-location))
				  (cdr slot-location)))
			  (t
			   (slot-missing class nil slot-name 'slot-value)))))
	(if (eq value unbound)
	    (slot-unbound class nil slot-name)
	    value)))))

-- 
Pierre Mai <····@cs.tu-berlin.de>	http://home.pages.de/~trillian/
  "Such is life." -- Fiona in "Four Weddings and a Funeral" (UK/1994)