[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GOOPS: calling next-method with different arguments.

From: Tobias Brandt
Subject: Re: GOOPS: calling next-method with different arguments.
Date: Sun, 21 Apr 2013 19:17:47 +0200

I just noticed something: next-method *already* supports calling it with different arguments. It's just not documented.

(define-class <foo> ())
(define-class <bar> (<foo>))

(define-method (f (self <foo>) (x <number>))
    (format #t "foo: ~a\n" x))

(define-method (f (self <bar>) (x <number>))
    (next-method self (1+ x))  ;; change arguments
    (format #t "bar: ~a\n" x))

(f (make <bar>) 1)

foo: 2
bar: 1

On 21 April 2013 18:05, Tobias Brandt <address@hidden> wrote:

thanks for your input. I tried to avoid the whole next-method issue entirely and defined a method for make on bar's metaclass instead.

(use-modules (oop goops))

(define-class <foo> () (s #:init-keyword #:s))
(define-class <bar-class> (<class>))
(define-class <bar> (<foo>) #:metaclass <bar-class>)

(define-method (make (self <bar-class>) (i <integer>))
    (make self #:s (number->string i)))

Now we can do:

(slot-ref (make <bar> 1) 's)
=> "1"

Old constructor still works (it has to, because it's called in the method we just defined):

(slot-ref (make <bar> #:s "baz") 's)
=> "baz"

However, I have no idea what the performance implications of creating a new metaclass are. IIRC, in Smalltalk every class has its own metaclass automatically and that doesn't seem to cause any problems.


On 20 April 2013 00:58, Panicz Maciej Godek <address@hidden> wrote:
I've been trying to make some deeper inquiry. It turns out that the case is not as simple as I thought.
I came up with the following function
(use-modules (oop goops) (ice-9 match) (srfi srfi-1))

(define (parent-methods method class)
  (let* ((supers (class-direct-supers class))
         (super? (lambda(c)(find (lambda(s)(eq? c s)) supers))))
    (filter-map (match-lambda((method (? super? super) args ...) method) (else #f))
(map (lambda(m)(cons m (method-specializers m)))
                     (generic-function-methods method)))))

it works more or less as expected, at least for initializers (because it is defined in such way that it only looks at the method's first argument) -- it does return a list of parents' initializers.

The problem appears if a parent's initializer contains (next-method) invocation. Otherwise (if there's no call to (next-method)) the method contains a procedure in its 'procedure' slot, which can be accessed using `method-procedure`, and then called or applied in a regular manner. 
However, if there is a call to (next-method) in a macro, the `method-procedure` called on such method returns #f. I think the idea is that methods are meant to be called from the context of `apply-generic` and next-method is a continuation, but I haven't figured out how it works exactly.
Anyway, the thing isn't as simple as I thought and perhaps someone else could try another approach.

Sorry for causing confusion!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]