6.001/Recitation 19
Rob Speer
Contents |
Problem to ponder
- Given a list, how can you determine if it is circular or not in linear time?
- How about a tree?
Regressing to a simpler OO system
The Project 4 OO system is fairly friendly to program with, but you'll notice that it involves a lot of backend code. The concepts of OO show up in simpler systems, and these simpler systems might be on the test.
Useful syntax: case
case compares a symbol with a list of possibilities. It seems to be particularly designed for message handling.
Here's a stupid little function that takes in the symbols 'one, 'two, or 'three and returns 1, 2, or 3, or 0 if it doesn't match any of those:
(λ (sym)
(case sym
((one) 1)
((two) 2)
((three) 3)
(else 0)))
A message handler
The fundamental properties of an OO object are that it stores state and responds to messages. We can get this with a fairly simple procedure. As an example, here's a message handler that acts like an OO version of a pair:
(define (pair car cdr)
(λ (message)
((CAR) (λ () car))
((CDR) (λ () cdr))
((SET-CAR!) (λ (val) (set! car val)))
((SET-CDR!) (λ (val) (set! cdr val)))
(else (error "unknown message"))))
- How do you call a method in this system?
- What does the environment diagram look like?
Adding self
These simple message handlers have no concept of self; they can't consider themselves as an object that can respond to messages. One way to solve that is to pass self as the first argument for every message.
...
((POP) (λ (self)
(begin0
((self 'CAR) self)
(set! car ((cdr 'CAR) cdr))
(set! cdr ((cdr 'CDR) cdr))))
...
But wait. Aren't we supposed to be using the methods we provide?
...
((POP) (λ (self)
(begin0
(let ((my-car ((self 'CAR) self))
(my-cdr ((self 'CDR) self)))
my-car
((self 'SET-CAR!) self ((my-cdr 'CAR) my-cdr))
((self 'SET-CDR!) self ((my-cdr 'CDR) my-cdr)))))
...
This is getting repetitive and hard to read. An ask function would be nice.
...
((POP) (λ (self)
(begin0
(ask self 'CAR)
(ask self 'SET-CAR! (ask (ask self 'CDR) 'CAR))
(ask self 'SET-CDR! (ask (ask self 'CDR) 'CDR)))
...
- So let's write this wonderful
askfunction.
Adding inheritance
Instead of giving up when the case statement won't handle the method, pass it on to another class.
- Is it okay to
askyour superclass? - We can write simple inheritance inline. Examples in OO systems like this tend to use a helper function called
get-methodto look up superclass methods, though. What can they gain this way?
Adding IS-A
There's a few ways to do this, some more robust than others.
Back to mutation
Draw a box and pointer diagram for what happens here:
(define y 7) (define z (let ((x (list 'a (quote (b c)) y)))
(set! y (cdr x))
(set-cdr! x (car (cdr x)))
x))
z
Finally, we'll talk about the problem to ponder, detecting a circular list or tree.
