UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture07/ tree-size.rkt
#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)