I'm trying to make simple OOP in racket. To do so, I want to create a macro with define-syntax that will generate the class.
All the techniques that I found online for the dispatcher demand to write a pattern matching by hand but I want this macro to generate the method dispatcher.
For now, i have something like that:
(define-syntax class
(syntax-rules ()
((_ (name . args) body ...)
(define (name . args)
body ...
(define (dispatcher m) (eval m))
dispatcher))))
And i want it to do something like:
(class (Point x y)
(define getx x)
(define gety y))
(class (Rectangle height width)
(define getheight height)
(define getwidth width))
> (define p (Point 1 2))
> (p 'getx)
1
> (define r (Rectangle 10 15))
> (r 'getwidth)
15
I know that eval will not work here because the method will be define in a local scope and eval does not see it. I tried to create a namespace around (define (name . args)) but then the eval doesn't see the x and y at the object instantiation ((Point 1 2)).
Is there a way to get the method by it's quote form? Or is it possible to generate the dispatcher in another way?
For instance
(define-syntax define-class
(syntax-rules (define)
[(_ (name slot ...)
(define (meth self arg ...) body ...)
...)
(define (name slot ...)
(let ((dispatch `((meth . ,(λ (self arg ...) body ...))
...)))
(define (this msg . args)
(let ([m (assq msg dispatch)])
(unless m
(error 'name "no method for ~S" msg))
(apply (cdr m) this args)))
this))]))
Then
(define-class (2d-point x y)
(define (px self) x)
(define (py self) y)
(define (set-px! self nx)
(set! x nx))
(define (set-py! self ny)
(set! x ny)))
and now
> (define p (2d-point 0 0))
> (p 'px)
0
> (p 'set-px! 2)
> (p 'px)
2
> (p 'pz)
2d-point: no method for pz
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With