recitation 16: message passing ======================================================================== Warmup exercises: * write a procedure max that takes in 2 or more numbers and returns the largest number. (Hint: you'll need to use ". args") (max 3 1 6 4 2) -> 6 (max 3 1) -> 3 (define (max a b . args) (fold-right (lambda (x m) (if (> x m) x m)) a (cons b args))) * write a procedure add-numbers-in-lists that takes in two lists of numbers and adds them all together. Use apply. (add-numbers-in-lists (list 1 2 3) (list 4 5 6)) -> 21 (define (add-numbers-in-lists a b) (apply + (append a b))) * generalize add-numbers-in-lists to take 1 or more lists of numbers. (add-numbers-in-lists (list 1 2 3) (list 4) (list) (list 5 6)) -> 21 (define (add-numbers-in-lists a . lists) (apply + (fold-right append a lists))) * write a procedure multi-list-map that takes in an op on n arguments and n lists (where n >= 1) and does the right thing. (Hint: you'll need to use ". args" and apply) (multi-list-map max (list 0 2 4 6 8) (list 8 6 4 2 0) (list 5 5 5 5 5)) -> (8 6 5 6 8) (define (multi-list-map op lst . lists) (if (null? lst) nil (cons (apply op (map car (cons lst lists))) (apply multi-list-map (cons op (map cdr (cons lst lists))))))) ======================================================================== how do we build a system to apply generic operations on different types of data? * tagged data & "dispatch on type" * message passing - make the data into "smart" procedures with state - procedures can "store" data (environment pointer part) - methods for manipulating data * object oriented programming - message passing + lots of goodies - more on Thursday & Friday - next project! how easy is it to break the system into modules? how easy is it to extend the system? organize the types & operations into a table, then group by row or by column, either by operation or data type class vs. instance ======================================================================== Write code that results in this environment diagram (some things may not be drawn):
(define foo (let () (lambda (x) x))) - OR - (define foo ((lambda () (lambda (x) x)))) ======================================================================== Write code that results in this environment diagram (some things may not be drawn):
(define thing (let ((x 10)) (lambda (op) (lambda (y) (op x y))))) (define foo (thing +)) (define bar (thing *)) ======================================================================== Let's write a bank atm system in message passing style with the following behavior: (define alice-atm (make-account 'alice)) (alice-atm 'balance) => 0 (alice-atm 'add 100) (alice-atm 'balance) => 100 (alice-atm 'subtract 20) (alice-atm 'balance) => 80 (alice-atm 'name) => alice (alice-atm 'primary-name) => alice (define bob-atm (alice-atm 'make-joint 'bob)) (bob-atm 'name) => bob (bob-atm 'primary-name) => alice (bob-atm 'balance) => 80 (bob-atm 'add 100) (bob-atm 'balance) => 180 (bob-atm 'subtract 20) (bob-atm 'balance) => 160 (alice-atm 'balance) => 160 first sketch the environment diagram you'll need to implement, then write the code. (define (make-account primary-name) (let ((balance 0)) (define (make-card name) (lambda (msg . args) (cond ((eq? msg 'name) name) ((eq? msg 'primary-name) primary-name) ((eq? msg 'balance) balance) ((eq? msg 'add) (set! balance (+ balance (car args)))) ((eq? msg 'subtract) (set! balance (- balance (car args)))) ((eq? msg 'make-joint) (make-card (car args))) (else "unknown message")))) (make-card primary-name))) The environment diagram for the above solution:
========================================================================