% -*- Mode: Tex -*-

\def\AnswerSheet{1}

\input 6001mac.tex

\begin{document}

\psetheader{Spring Semester, 1999}{Recitation -- Friday, April 2}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

{\Large\bf 1. Object Oriented Programming}

Below is the object oriented system from the April 1st Lecture Notes
(just included for reference):

\begin{tabular}{p{3.0in}p{3.5in}} 
\beginlisp
(define (get-method message object)
  (object message))
\null
(define method? procedure?)
\endlisp
&
\beginlisp
(define (ask object message . args)
  (let ((method (get-method message object)))
    (if (method? method)
        (apply method object args)
        (error "No method for mesage" message))))
\endlisp
\end{tabular}

{\Large\bf 2. Object Oriented Stacks}

Using this object oriented style, write the function {\tt
create-stack} that will create a stack object.  Recall that stacks are
data structures that include the operations {\tt push}, {\tt pop},
{\tt peek}, and {\tt clear}.  Objects get {\tt push}ed on and {\tt
pop}ped off the stack in a last-in-first-out manner.  
Complete the function {\tt create-stack}.

\begin{tabular}{p{3.5in}p{2.5in}}
\beginlisp
(define (create-stack)
\ANSWER{
  (let ((value '()))
}
    (lambda (message)
      (case message
        ((PUSH)
\ANSWER{
         (lambda (self new)
           (set! value (cons new value)))})
        ((PEEK)
\ANSWER{
         (lambda (self) (car value))})
        ((CLEAR)
\ANSWER{
         (lambda (self) (set! value '()))})
        ((POP)
\ANSWER{
         (lambda (self)
           (let ((return (ask self 'peek)))
             (set! value (cdr value))
             return))})))))
\endlisp
&
\beginlisp
(define s (create-stack))
(ask s 'push 5)
(ask s 'push 3)
(ask s 'pop)            ==> 3
(ask s 'push 1)
(ask s 'pop)            ==> 1
(ask s 'pop)            ==> 5
\endlisp
\end{tabular}

{\Large\bf 3. Object Oriented Variables}

Next, let's write an abstraction for variables in the object oriented
style.  We do this so that in addition to the {\tt get} (lookup) and
{\tt set!} operations that we have in scheme, we also want to
implement an {\tt undo!} method that un-does the last {\tt set!}ing of
the variable.  We want to store an arbitrary number of undos.  How can
we use stacks to help us with this {\tt undo!}?  Complete the code for
{\tt create-var}.

\begin{tabular}{p{3.5in}p{2.5in}}
\beginlisp
(define (create-var value)
\ANSWER{
  (let ((undo (create-stack)))
    (ask undo 'push value)
}
    (lambda (message)
      (case message
        ((SET!)
\ANSWER{
         (lambda (self new)
           (ask undo 'push new))})
        ((GET)
\ANSWER{
          (lambda (self)
            (ask undo 'peek))})
        ((UNDO!)
\ANSWER{
         (lambda (self)
           (ask undo 'pop))})))))
\endlisp
&
\beginlisp
(define a (create-var 1))
(ask a 'get)                    ==> 1
(ask a 'set! 2)                 
(ask a 'get)                    ==> 2
(ask a 'undo!)
(ask a 'get)                    ==> 1
\endlisp
\end{tabular}

\newpage
{\Large\bf 4. Object Oriented Pairs}

Well, we wrote it for one variable, now let's write it for pairs.
Consider the function {\tt create-pair} that generates a pair of
variables (the car and the cdr) that you can get or set.  When the
message {\tt undo!} is sent, the last setting gets undone (be it a
{\tt set-car!} or {\tt set-cdr!}.  Consider the following example 
and complete the code for {\tt create-pair}.

\begin{tabular}{p{3.5in}p{2.5in}}
\beginlisp
(define (create-pair car-val cdr-val)
\ANSWER{
  (let ((last-change (create-var '()))
        (the-car (create-var car-val))
        (the-cdr (create-var cdr-val)))
}
   (lambda (message)
    (case message
      ((SET-CAR!)
\ANSWER{
       (lambda (self new)
         (ask last-change 'set! 'car)
         (ask the-car 'set! new))})
      ((SET-CDR!)
\ANSWER{       (lambda (self new)
         (ask last-change 'set! 'cdr)
         (ask the-cdr 'set! new))})
      ((CAR)
\ANSWER{       (lambda (self) (ask the-car 'get))})
      ((CDR)
\ANSWER{       (lambda (self) (ask the-cdr 'get))})
      ((PRINT)
       (lambda (self)
         (display (ask self 'car))
         (display "."
         (display (ask self 'cdr))))
      ((UNDO!)
\ANSWER{       (lambda (self)
         (case (ask last-change 'undo!)
           ((CAR) (ask the-car 'undo!))
           ((CDR) (ask the-cdr 'undo!))))})))))
\endlisp
&
\beginlisp
(define p (create-pair 1 2))
(ask p 'print)         ==> (1 . 2)
(ask p 'set-car! 3)  
(ask p 'print)         ==> (3 . 2)
(ask p 'set-cdr! 4)  
(ask p 'print)         ==> (3 . 4)
(ask p 'set-car! 5)  
(ask p 'print)         ==> (5 . 4)
(ask p 'undo!)       
(ask p 'print)         ==> (3 . 4)
(ask p 'undo!)       
(ask p 'print)         ==> (3 . 2)
(ask p 'undo!)       
(ask p 'print)         ==> (1 . 2)
\endlisp
\end{tabular}

{\Large\bf 5. Object Oriented Variables with Redo!}

Now we have the ability to {\tt undo!} the results to set, let's add a
{\tt redo!} feature, such that successive calls to {\tt undo!} and be
taken back using a call to {\tt redo!}.  Complete the code for {\tt
create-var}.

\begin{tabular}{p{3.5in}p{2.5in}}
\beginlisp
(define (create-var value)
\ANSWER{
  (let ((undo (create-stack))
        (redo (create-stack)))
   (ask undo 'push value)
}
   (lambda (message)
    (case message
      ((SET!)
\ANSWER{
       (lambda (self new)
         (ask redo 'clear)
         (ask undo 'push new))})
      ((GET)
\ANSWER{        (lambda (self)
          (ask undo 'peek))})
      ((UNDO!)
\ANSWER{       (lambda (self)
         (ask redo 'push (ask undo 'pop)))})
      ((REDO!)
\ANSWER{       (lambda (self)
         (ask undo 'push (ask redo 'pop)))})))))
\endlisp
&
\beginlisp
(define a (create-var 1))
(ask a 'set! 2)
(ask a 'undo!)
(ask a 'get)    ==> 2
(ask a 'undo!)
(ask a 'get)    ==> 1
(ask a 'redo!)
(ask a 'get)    ==> 2
\endlisp
\end{tabular}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\end{document}



