Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a method dispatcher with define-syntax in racket

Tags:

racket

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?

like image 576
Julien Avatar asked Oct 29 '25 21:10

Julien


1 Answers

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
like image 169
ignis volens Avatar answered Nov 02 '25 23:11

ignis volens



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!