# OBJECT introduce simple form of typing, for ease of documentation.
       # An object is simply a function that takes an argument.
       # The argument is the method to call on the object.
       # Types are here taken to be just the existence of a particular method,
       # with that method returning an object of the appropriate type.
[hear] (define make-integer
         (lambda (v)
           (lambda (x)
             (if (= (x) int)
             (v)
             0))));

[hear] (define objectify
         (? x
            (if (number? (x))
            (make-integer (x))
            (x))));

[hear] (define instanceof
         (lambda (T t)
           (if (number? (t))
           (= (T) int)
           (not (number? ((objectify (t)) (T)))))));

       # add version of lambda that allows types to be declared
[hear] (define prev-translate (translate));

[hear] (define translate
         (let ((prev (prev-translate)))
           (? x
             (if (number? (x))
               (prev (x))
               (if (= (head (x)) lambda)
                 (let ((formals (head (tail (x))))
                       (body (head (tail (tail (x))))))
                   (if (> (list-length (formals)) 0)
               (if (number? (last (formals)))
                   (translate
                    (vector
                     lambda
                     (except-last (formals))
                     (vector ? (last (formals)) (body))))
                   (let ((formal-name (first (last (formals))))
                     (formal-type (second (last (formals)))))
                     (translate
                      (vector
                   lambda
                   (except-last (formals))
                   (vector
                    ?
                    (formal-name)
                    (vector
                     let
                     (vector (vector
                          (formal-name)
                          (vector
                           (vector objectify (vector (formal-name)))
                           (formal-type))))
                     (body)))))))
               (translate (body))))
                 (prev (x)))))));

       # add conditional form
[hear] (define prev-translate (translate));

[hear] (define translate
         (let ((prev (prev-translate)))
           (? x
             (if (number? (x))
               (prev (x))
               (if (= (head (x)) cond)
                 (let ((cnd (head (tail (x))))
                       (rem (tail (tail (x)))))
                   (if (> (list-length (rem)) 0)
               (translate
                (vector
                         if
                 (first (cnd))
                 (second (cnd))
                 (prepend cond (rem))))
               (translate (cnd))))
                 (prev (x)))))));

[hear] (= 99 (cond 99));

[hear] (= 8 (cond ((true) 8) 11));

[hear] (= 11 (cond ((false) 8) 11));

[hear] (= 7 (cond ((false) 3) ((true) 7) 11));

[hear] (= 3 (cond ((true) 3) ((true) 7) 11));

[hear] (= 11 (cond ((false) 3) ((false) 7) 11));

[hear] (define remove-match
         (lambda (test lst)
           (if (> (list-length (lst)) 0)
           (if (test (head (lst)))
               (remove-match (test) (tail (lst)))
               (prepend (head (lst)) (remove-match (test) (tail (lst)))))
           (lst))));

[hear] (define remove-element
         (lambda (x)
           (remove-match (lambda (y) (= (y) (x))))));

[hear] (list= (vector 1 2 3 5) (remove-element 4 (vector 1 2 3 4 5)));

[hear] (list= (vector 1 2 3 5) (remove-element 4 (vector 1 4 2 4 3 4 5)));

[hear] (define return
         (lambda (T t)
           (let ((obj (objectify (t))))
             (obj (T)))));

[hear] (define tester
         (lambda ((x int) (y int))
           (return int (+ (x) (y)))));

[hear] (= 42 (tester (make-integer 10) (make-integer 32)));

[hear] (= 42 (tester 10 32));

[hear] (define reflective
         (lambda (f)
           ((lambda (x)
              (f (lambda (y) ((x (x)) (y)))))
            (lambda (x)
              (f (lambda (y) ((x (x)) (y))))))));