(define-module (catbird observer) #:use-module (catbird config) #:use-module (oop goops) #:export ( on-change)) ;; This is a hack to deal with the fact that specializing GOOPS ;; accessors does not compose with inheritance. ;; ;; See ;; https://dthompson.us/issues-with-object-oriented-programming-in-guile.html ;; for details. (define-class ()) (define-generic on-change) (define-method (observer-slot? (slot )) (get-keyword #:observe? (slot-definition-options slot))) (define-method (compute-setter-method (class ) slot) (if (observer-slot? slot) ;; Wrap the original setter procedure with a new procedure that ;; calls the on-change method. (make #:specializers (list class ) #:procedure (let ((slot-name (slot-definition-name slot)) (proc (method-procedure (next-method)))) (lambda (obj new) (let ((old (and (slot-bound? obj slot-name) (slot-ref obj slot-name)))) (proc obj new) (on-change obj slot-name old new))))) (next-method))) (define-class () #:metaclass )