;;;;-------------------------------
;;;; Basics
(define rand (let ((q 1))
(lambda ()
(cond ((eq? q 15) (set! q 1) q)
(else (set! q (+ q 1)) q)))))
(define obj
(lambda (state)
(lambda msg
(let ((a state))
(letrec ((d (lambda (x) a)))
(if (eq? (car msg) 'change-state)
(obj (car (cdr msg)))
(if (eq? (car msg) 'report-state)
a
'())))))))
(define test
(lambda (obj n)
(if (= n 0)
'()
(cons (obj 'report-state) (test (obj 'change-state (rand)) (- n 1))))))
;;;;-----------------------------
;;;; Try Stacks
(define stack
(lambda (s)
(lambda msg
(let ((a s))
(letrec
((push (lambda (x) (stack (cons x a))))
(pop (lambda () (stack (cdr a))))
(top (lambda () (car a)))
(show (lambda () a)))
(case (car msg)
('top (top))
('push (push (car (cdr msg))))
('pop (pop))
('show (show))
(else '())))))))
;;;;-------------------------------
;;;; Tests
(define destroy-stack
(lambda (s)
(if (null? (s 'show))
'()
(cons (s 'show) (destroy-stack (s 'pop))))))
(define build-stack
(lambda (s n)
(if (= n 0)
'()
(cons (s 'show) (build-stack (s 'push n) (- n 1))))))
(define build-and-destroy-stack
(lambda (s n)
(letrec ((bs (lambda (s^ n^) (if (= n^ 0) s^ (bs (s^ 'push n^) (- n^ 1))))))
(append (build-stack s n) (destroy-stack (bs s n))))))