#lang racket
(require [only-in plait test test/exn error print-only-errors])
(define (msg obj selector . args)
(apply (obj selector) args))
(define (mt)
(lambda (m)
(case m
[(sum) (lambda () 0)])))
(define (node v l r)
(lambda (m)
(case m
[(sum) (lambda () (+ v (msg l 'sum)
(msg r 'sum)))])))
(define (node/size v l r)
(let ([parent-object (node v l r)])
(lambda (m)
(case m
[(size) (lambda () (+ 1 (msg l 'size)
(msg r 'size)))]
[else (parent-object m)]))))
(define (mt/size)
(let ([parent-object (mt)])
(lambda (m)
(case m
[(size) (lambda () 0)]
[else (parent-object m)]))))
(define a-tree/size
(node/size 10
(node/size 5 (mt/size) (mt/size))
(node/size 15
(node/size 6 (mt/size) (mt/size))
(mt/size))))
(test (msg a-tree/size 'sum) (+ 10 5 15 6))
(test (msg a-tree/size 'size) 4)