#lang plai ;; On object is list containing ;; - a hash table for fields ;; - a hash table for methods, where each method ;; is a function that takes `this` and one argument (define-syntax-rule (object ([field-id field-expr] ...) [method-id body-expr] ...) (list (make-hash (list (cons 'field-id field-expr) ...)) (make-hash (list (cons 'method-id (method body-expr)) ...)))) ;; `(method body)` expands to `(lambda (this arg) body)`, but ;; in a way that allows `body` to refer to `this` and `arg' (define-syntax (method stx) (syntax-case stx () [(method body) (with-syntax ([this-id (datum->syntax #'body 'this)] [arg-id (datum->syntax #'body 'arg)]) #'(lambda (this-id arg-id) body))])) ;; Extract a field form the first hash table. (define-syntax-rule (get o-expr f-id) (hash-ref (first o-expr) 'f-id)) ;; Extract a method form the second hash table. (define-syntax-rule (send o-expr m-id arg-expr) (let ([o o-expr]) ((hash-ref (second o) 'm-id) o arg-expr))) ;; ---------------------------------------- (define-syntax-rule (rectangle init-w init-h) (object ([w init-w] [h init-h]) [area (* (get this w) (get this h))] [bigger-than? (> (send this area 0) arg)])) (define r (rectangle 10 15)) (send r area 0) (send r bigger-than? 100)