----------------------------------------- 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