rendered paste body(require (lib "defmacro.ss"))
(require (lib "match.ss"))
(require (lib "etc.ss"))
(require (lib "string.ss"))
(define y
(λ (x)
((λ (p) (x (λ n (apply (p p) n))))
(λ (p) (x (λ n (apply (p p) n)))))))
(define-macro y-λ
(λ (params . body)
(let ((self-symbol (car params))
(rest-params (cdr params)))
`(y (λ (,self-symbol) (λ ,rest-params ,@body))))))
(define-macro ->
(λ (object key . params)
(let ((value (gensym)))
`(let ((,value (,object ',key)))
(if (procedure? ,value)
(apply ,value (cons ,object (list ,@params)))
,value)))))
(define-macro :=
(λ (object key value)
`(apply (,object 'set-slot) (list ,object ',key ,value))))
(define-macro method
(λ (params . body)
`(λ ,@(list (cons 'self params)) ,@body)))
(define object
(let ((table (make-hash-table)))
(map (λ (pair) (hash-table-put! table (car pair) (cadr pair)))
`(
(clone
,(method ()
(let ((result (make-object self)))
(-> result initialize)
result)))
(get-slot
,(method (key)
(hash-table-get (self) key)))
(set-slot
,(method (key value)
(hash-table-put! (self) key value)
self))
))
(y-λ (self key) (hash-table-get table key '()))))
(define make-object
(lambda (&optional (parent object))
(let ((table (make-hash-table)))
(hash-table-put! table 'protos (list parent))
(y (λ (self) (lambda (&optional key)
(if (not key)
table
(let ((value (hash-table-get table key '())))
(if (null? value)
(unless (eq? 'protos key)
(let proto-lookup ((protos (-> self protos)))
(if (null? protos)
'()
(let* ((proto (car protos))
(value (proto key)))
(if (null? value)
(proto-lookup (cdr protos))
value)))))
value)))))))))
(define person (-> object clone))
(:= person with
(method (name)
(let ((result (-> self clone)))
(:= result name name))))
(:= person greet
(method ()
(display "Hi, my name is ")
(display (self 'name))
(display ".")(newline)))
(define student (-> person clone))
(:= student initialize
(λ (self)
(:= self studies '())))
(:= student study
(λ (self . subjects)
(:= self studies (append subjects (-> self studies)))))
(:= student greet
(method ()
((person 'greet) self)
(display "I study: ")
(let ((studies (reverse (-> self studies))))
(map (λ (subject) (display subject) (display ", ")) (cdr studies))
(if (> (length studies) 1)
(display "and "))
(display (car studies)))
(display ".")(newline)))
(define bob (-> person with "Bob"))
(-> bob greet) ; Hi, my name is Bob.
(define fred (-> student with "Fred"))
(-> fred study "Calculus" "French" "Music")
(-> fred greet) ; Hi my name is Fred. I study: Calculus, French, and Music.