[plt-scheme] PLT Object System
On Sun, Feb 20, 2005 at 11:19:57AM -0500, David J. Neu wrote:
> Hi,
>
> I have a question about the PLT object system ...
<SNIP>
> Now similarly, suppose you'd like to define a class to have a GET and
> a SET procedure for a variable, and that you'd like to be able to
> "override" these procedures on a one-time basis without bothering to
> derive a new class.
>
> The example below works up until the last line:
>
> (require (lib "class.ss"))
>
> (define foo%
> (class object%
> (init-field x
> (get (lambda () x))
> (set (lambda (_x) (set! x _x))))
> (set x)
> (super-new)))
>
> (define bar (new foo% (x 2)))
> (display (get-field x bar)) (newline)
>
> (define barbar (new foo% (x 2) (get (lambda () (add1 x)))))
> (display (send get x barbar)) (newline) ;; FAILS - no GET method
~~~~~~~~~~~~~~~~~~~
I'm assuming you meant (send barbar get) here, but that's not the
problem.
(Further, it's not obvious to me what the (set x) expression in your
definition of foo% does, but again, I don't think this is relevant.)
> It seems that their is a differentiation between fields and methods
> that does not exist in "the rest" of Scheme, so the idiom used to
> parametrize a procedure in my first example doesn't work.
That's correct, yes. (IIRC, in an earlier class system, a method was
just a field whose value was a function. That went away with either
v200 or v100, I don't remember which.)
> Is there a way to do this?
It's verbose, but you can do this by adding a level of indirection:
(define foo%
(class object%
(init-field x
(_get (lambda (x) x))
(_set (lambda (_x) (set! x _x))))
(define/public get (lambda () (_get x)))
(define/public set (lambda (x) (_set x)))
(super-new)))
> (define bar (new foo% [x 2]))
> (get-field x bar)
2
> (send bar get)
2
> (define bar2 (new foo% [x 2] [_get add1]))
> (get-field x bar)
2
> (get-field x bar2)
2
> (send bar2 get)
3
Note that I had to change your interface slightly; the _get init arg now
takes one parameter. Otherwise, you'd have to do something like this
(define bar3 (new foo% [x 2] [_get (lambda () (add1 x))]))
which doesn't work, because x isn't bound in this expression.
> Do generics have a role?
I didn't actually try this, but I don't think they'll help. According
to the manual (in 299.31), generics only allow access to methods, and
neither get nor set is a method in your original definition of foo%. I
could be completely wrong here, though.
And while my solution works, there may well be other alternatives.
Richard