unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* [GOOPS] Accessing a class slot
@ 2004-07-20 17:21 Ludovic Courtès
  2004-07-25 21:17 ` [1.6.4 GOOPS] no (next-method) in accessor? Steve Tell
  0 siblings, 1 reply; 3+ messages in thread
From: Ludovic Courtès @ 2004-07-20 17:21 UTC (permalink / raw)


Hi,

I noticed (using Guile 1.6.4) that trying to access a class-wide slot
(eg. via `class-slot-ref') before creating an instance of that class
always fails.  However, it does work once at least one instance of the
class has been created via `make'.  This behavior looks quite weird to
me:  I was expecting class-wide slots to be available right after the
class has been defined (just like C++ `static' class attributes are).

In particular, I wanted to access a class slot from within that class'
`initialize' method which turns out to not be feasible because of this.
I worked around it by creating a particular metaclass for the class in
question and then by specializing `slot-unbound' for that metaclass:

  (define-class <class-wide-slots-metaclass> (<class>))

  (define-class <the-class-with-class-wide-slots>
    [...]
    #:metaclass <class-wide-slots-metaclass>)

  (define-method (slot-unbound (class <class-wide-slots-metaclass>) slot-name)
    (if (eq? <the-class-with-class-wide-slots> class)
        '()
        (next-method)))

However, although interesting, this technique is definitely not the
right way IMO.  ;-)   What do people think about this issue?

Thanks,
Ludovic.


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [1.6.4 GOOPS] no (next-method) in accessor?
  2004-07-20 17:21 [GOOPS] Accessing a class slot Ludovic Courtès
@ 2004-07-25 21:17 ` Steve Tell
  2004-07-26 17:51   ` Andy Wingo
  0 siblings, 1 reply; 3+ messages in thread
From: Steve Tell @ 2004-07-25 21:17 UTC (permalink / raw)



I just started working with (oop goops) in guile 1.6.4, and have run into 
a problem.   In a subclasse's accessor's #:slot-set! routine, I wanted to 
do some additional setup and checking and then call the base class's 
accessor to do most of the work.  
But even though the documentation suggests that accessors are generic 
functions, (next-method) doesn't seem to work.

Is there somthing I'm doing wrong in the example below?  Or are accessors 
not really full-featured generic functions in this sense?

Steve

(P.S. Since my previous OO experience has been with Eiffel, 1995-vintage
C++ and perl, parts of goops are a bit alien to me.  But so far I like
it.)





(use-modules  (ice-9 format) (oop goops) (oop goops describe))

(define (ctrlpt-print-statechange o old new)
  (format #t "--ctrlpt ~s ~s=>~s\n" (name o) old new))

(define-class <ctrlpt> ()
  (name #:init-value "" #:init-keyword #:name #:getter name)
  (curstate #:init-value #f)
  (hook #:init-thunk (lambda () (make-hook 3)))
  (state #:accessor state
	 #:allocation #:virtual 
	 #:slot-ref (lambda (o) (slot-ref o 'curstate))
	 #:slot-set! (lambda (o ns)
		       (let ((oldval (slot-ref o 'curstate)))
			 (slot-set! o 'curstate ns)
			 (run-hook (slot-ref o 'hook) o oldval ns)))
	 )
  (verbose #:accessor verbose
	   #:allocation #:virtual
	   #:init-value #f
	   #:slot-ref (lambda (o) 
			(not(not(member ctrlpt-print-statechange 
					(hook->list (slot-ref o 'hook))))))
	   #:slot-set! (lambda (o v)
			 (if v
			     (add-hook! (slot-ref o 'hook)
					ctrlpt-print-statechange)
			     (remove-hook! (slot-ref o 'hook) 
					   ctrlpt-print-statechange)))
	   )
)

(define-class <boolean-ctrlpt> (<ctrlpt>)
  (state 
   #:allocation #:virtual
   #:accessor state
   #:slot-ref (lambda (o) (next-method))
   #:slot-set! (lambda (o ns)
		 (if (not (boolean? ns))
		     (error "<boolean-ctrlpt> new state must be boolean"))
		 (next-method) ; fails ERROR: No next method when calling #<<generic> setter:state (2)>
)))

(define-method (increment! (o <boolean-ctrlpt>))
  (set! (state o) (not (state o))))

; blowing off accessors and defining our own generic methods works
(define-method (ctrlpt-set-state! (o <ctrlpt>) ns)
  (let ((oldval (slot-ref o 'curstate)))
    (slot-set! o 'curstate ns)
    (run-hook (slot-ref o 'hook) o oldval ns)))

(define-method (ctrlpt-set-state! (o <boolean-ctrlpt>) ns)
  (if (not (boolean? ns))
      (error "<boolean-ctrlpt> new state must be boolean"))
  (next-method)
)


(define cp (make <ctrlpt> #:name "testpt"))
(slot-set! cp 'state #t)
(set! (state cp) #t)
(ctrlpt-set-state! cp #f)

(define bp (make <boolean-ctrlpt> #:name "btst"))
(ctrlpt-set-state! bp #t) ; works
(set! (state bp) #t)  ; fails  here
(increment! bp) ; fails here too






_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [1.6.4 GOOPS] no (next-method) in accessor?
  2004-07-25 21:17 ` [1.6.4 GOOPS] no (next-method) in accessor? Steve Tell
@ 2004-07-26 17:51   ` Andy Wingo
  0 siblings, 0 replies; 3+ messages in thread
From: Andy Wingo @ 2004-07-26 17:51 UTC (permalink / raw)


Hey Steve,

I looked at your code. I'm no expert, but here's what I see.

On Sun, 2004-07-25 at 17:17 -0400, Steve Tell wrote:
> In a subclasse's accessor's #:slot-set! routine

Here's where you go wrong. The slot-set! routine is not a generic
function, nor does it belong to the accessor. Instead, these arguments
to `make-class' are used by the default compute-get-n-set generic, which
uses them to explicitly set the get/set functions for a class.

There is no MOP specified for get and set functions, though. If you
wanted to implement something like this, you could define a metaclass
for the root <ctrlpt> class that implements a custom compute-get-n-set
method.

Here's some code from (gnome gobject gtype), as an example:

(define-class <set-once-class> (<class>))
(define-method (compute-get-n-set (class <set-once-class>) s)
  (case (slot-definition-allocation s)
    ((#:set-once)
     (create-set-once-g-n-s class s #f)) ;; returns (list getter setter)

    ((#:set-once-each-subclass)
     (create-set-once-g-n-s class s #t))

    ;; Chain up for the default allocation methods...
    (else (next-method))))

;; We have to inherit from class because we're a metaclass. We do that
;; via <set-once-class>. We have #:set-once slots, so we also need to
;; have <set-once-class> as our metaclass.
(define-class <gtype-class> (<set-once-class>)
  (gtype #:allocation #:set-once)
  (gtype-class #:allocation #:set-once)
  #:metaclass <set-once-class>)

In your case, since <ctrlpt> isn't a metaclass the supers list would be
empty.

Hope this helps,
-- 
Andy Wingo <wingo@pobox.com>
http://ambient.2y.net/wingo/


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2004-07-26 17:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-20 17:21 [GOOPS] Accessing a class slot Ludovic Courtès
2004-07-25 21:17 ` [1.6.4 GOOPS] no (next-method) in accessor? Steve Tell
2004-07-26 17:51   ` Andy Wingo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).