[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Chicken-users] Tinyclos - a bit disappointing for an ex-stklos user
From: |
Alex Shinn |
Subject: |
Re: [Chicken-users] Tinyclos - a bit disappointing for an ex-stklos user |
Date: |
Thu, 14 Sep 2006 17:35:26 +0900 |
On 9/14/06, felix winkelmann <address@hidden> wrote:
On 9/14/06, Matthew Welland <address@hidden> wrote:
> Is there a formal reason why tinyclos can't have its own namespace for
> methods? Or, is it just an implementation limitation?
>
> In STklos I was used to doing the following:
>
> (define-class <foo> ()
> ((bar :initform '())))
>
> (define-method length ((self <foo>))
> (length (slot-ref self 'bar)))
>
> (define a (make <foo>))
>
> (length a) => 0
>
> (define b '(1 2 3))
>
> (length b) => 3
>
> Which, IMHO was very nice. No such luck with Tinyclos.
Yes, Stklos' object-layer is much mor sophisticated than Chicken's.
But I don't think Stklos has actually a different namespace. IIRC length
is a method like everything else (I may be utterly wrong about this).
Actually, LENGTH is a primitive. When you define a new method as above,
if the current binding is not a generic, it is replaced with a generic that
defaults to the old binding. Chicken could do this quite easily. The
following code is exactly equivalent to what Stklos does:
(define-class <foo> () (bar))
;; convenience to allow keyword init slots on MAKE
(define-method (initialize (f <foo>) initargs)
(call-next-method)
(initialize-slots f initargs))
;; make LENGTH generic
(define old-length length)
(define-generic length)
(define-method (length x) (old-length x))
(define-method (length (x <foo>)) (length (slot-ref x 'bar)))
(define a (make <foo> 'bar '()))
(length a) => 0
You could also automate this:
(use lolevel)
(define-macro (define-generic* name . o)
(if (global-bound? name)
(let ((old-val (gensym)) (args (gensym)))
`(begin
(define ,old-val ,name)
(define-generic ,name ,@o)
(define-method (,name . ,args) (apply ,old-val ,args))))
`(define-generc ,name ,@o)))
and then replace the 3 lines used to make LENGTH generic
with a simple
(define-generic* length)
However, in general you really don't want to do this if you
care at all about performance, because your making core
forms that people depend on for speed very, very slow
(this goes for Stklos too, not just tinyclos).
At better approach is to use a separately named generic.
For instance, Gauche, which is heavily based on Stklos,
provides an abstract collections library with a SIZE-OF
generic which is used as you're using LENGTH above.
Thus where performance matters and you know you're using
a list use you can write LENGTH, otherwise use SIZE-OF.
If the object system is tightly integrated you can sometimes
have it both ways. Gauche provides methods like OBJECT-+,
OBJECT--, etc. which are used as defaults by + and -, etc.
Thus (+ 2 2) sees fixnums and performs fast dispatch, but
(+ some-object some-other-object) will look for the appropriate
method. If you really wanted, one could write a
numbers-tinyclos egg that does this.
--
Alex