-----------------------------------------
Tutorial notes #9 for 4/23 or 4/24/2007
TA: Stephen McCamant
Email: smcc@mit.edu
Location: 36-113A or 36-115
http://people.csail.mit.edu/smcc/6.001-sp07/
-----------------------------------------
Quiz 2
As threatened, this quiz was harder than
quiz 1; the median grade among my
students was 75. Two common
misunderstandings it highlighted:
- set! can only change variable bindings
in the environment. Its first argument
must be the name of a variable. Anything
else is a syntax error.
- If you want a variable to remember a
value between calls to a procedure, it
has to be defined outside that
procedure.
-----------------------------------------
Project 3
Quality is more important than quantity
in testing.
When feasible, test helpers separately.
ABSTRACTION VIOLATIONS on cells
Why copying grids usually doesn't work
Don't use mutation when return values or
loop parameters would work.
Convenient procedures to know about:
- (foldr append '() ...)
- list-ref
- member
Design choices in backtracking
User experience and the game
-----------------------------------------
Project 4
I'm hoping to be able to reply to all of
your extension proposals by Tuesday
night. Previews:
- If everything you've thought about
your idea can fit in one paragraph,
you should plan some more before
starting to implement.
- Conversely, if your idea involves
creating a completely different game,
beware of biting off more than you can
chew. Don't neglect the other parts of
the project, and if possible, do a
subset of your idea in the MIT world
first.
-----------------------------------------
Review of OO syntax
(define (create-<class> <params>)
(create-instance <class> <params>))
(define (<class> self <params>)
(let ((<superclass>-part
(<superclass> self <params>))
(<instance-var> <initial-val>)
(<instance-var> <initial-val>))
(make-handler
'<CLASS>
(make-methods
'<MSG>
(lambda (<args>) <body>)
'<MSG2>
(lambda (<args>) <body>))
<superclass>-part)))
(ask <instance> 'MESSAGE <args>)
-----------------------------------------
Appliances
For practice in modelling real-life
things with OO, let's make classes for
some home appliances. All our appliances
have on-off switches and a fuse that
blows and prevents them from operating
if they draw too much current.
(define (create-appliance manufacturer)
(create-instance appliance manufacturer))
(define (appliance self manufacturer)
(let ((switch-on? #f)
(fuse-blown? #f))
(make-handler
'appliance
(make-methods
'MANUFACTURER (lambda () manufacturer)
'SWITCH (lambda () (set! switch-on? (not switch-on?)))
'SWITCH-ON? (lambda () switch-on?)
'BLOW-FUSE (lambda () (set! fuse-blown? #t))
'FUSE-BLOWN? (lambda () fuse-blown?)
'ON? (lambda () (and switch-on?
(not (ask self 'fuse-blown?))))))))
(define (create-hair-dryer manufacturer)
(create-instance hair-dryer manufacturer))
(define (hair-dryer self manufacturer)
(let ((appliance-part (appliance self manufacturer))
(speed 0))
(make-handler
'hair-dryer
(make-methods
'SPEED (lambda () speed)
'SET-SPEED (lambda (s) (set! speed s))
'DRY (lambda ()
(if (ask appliance-part 'on?)
(printf "Hot air comes out~n")
(printf "Nothing happens~n"))))
appliance-part)))
(define (create-toaster manufacturer)
(create-instance toaster manufacturer))
(define (toaster self manufacturer)
(let ((appliance-part (appliance self manufacturer))
(darkness 0))
(make-handler
'hair-dryer
(make-methods
'DARKNESS (lambda () darkness)
'SET-DARKNESS (lambda (d) (set! darkness d))
'TOAST (lambda ()
(if (ask appliance-part 'on?)
(printf "Your bread turns golden brown~n")
(printf "Nothing happens~n"))))
appliance-part)))
;; A toaster-hair-dryer as a subclass of both toaster and hair-dryer
;; with the same manufacturer. (This is convenient, because they're
;; both things people do in the morning.) If you try to toast when the
;; hair-dryer is running too fast at the same time, the fuse will
;; blow.
;; In effect, the THD has two switches but only one manufacturer and
;; fuse. Notice the difference between using instance variables versus
;; methods, and between calling a method on self versus calling it on
;; a subobject.
(define (create-toaster-hair-dryer manufacturer)
(create-instance toaster-hair-dryer manufacturer))
(define (toaster-hair-dryer self manufacturer)
(let ((toaster-part (toaster self manufacturer))
(hair-dryer-part (hair-dryer self manufacturer)))
(make-handler
'toaster-hair-dryer
(make-methods
'SWITCH-TOASTER (lambda () (ask toaster-part 'switch))
'SWITCH-HAIR-DRYER (lambda () (ask hair-dryer-part 'switch))
'TOAST (lambda ()
(if (and (> (ask self 'speed) 5)
(> (ask self 'darkness) 5))
(ask self 'blow-fuse))
(ask toaster-part 'toast)))
toaster-part hair-dryer-part)))
(define t (create-toaster "Proctor-Silex"))
(define hd (create-hair-dryer "Sunbeam"))
(define thd (create-toaster-hair-dryer "Acme"))
(ask thd 'set-darkness 5)
(ask thd 'switch-toaster)
(ask thd 'set-speed 7)
(ask thd 'dry)
; -> Nothing happens
(ask thd 'switch-hair-dryer)
(ask thd 'dry)
; -> Hot air comes out
(ask thd 'toast)
; -> Your bread turns golden brown
(ask thd 'set-darkness 10)
(ask thd 'toast)
; -> Nothing happens
(ask thd 'set-darkness 3
(ask thd 'toast)
; -> Nothing happens
(ask thd 'dry)
; -> Nothing happens