UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture06/ state5.rkt
#lang racket
(require [only-in plait test test/exn error print-only-errors])

(define (msg obj selector . args)
  (apply (obj selector) args))

(define mk-num
  (let ([secret (gensym)])
    (lambda (init)
      (let ([amount init])
        (lambda (m)
          (cond
            [(equal? m secret) (lambda () amount)]
            [(equal? m 'add)
             (lambda (other)
               (mk-num (+ amount (msg other secret))))]
            [(equal? m 'odd?) (lambda () (odd? amount))]))))))

(define o2 (mk-num 2))
(define o3 (mk-num 3))
(define o4 (msg o2 'add o2))
(define o5 (msg o2 'add o3))
(test (msg o2 'odd?) #f)
(test (msg o3 'odd?) #t)
(test (msg o4 'odd?) #f)
(test (msg o5 'odd?) #t)