1 / 39

Example: explaining make-counter

Lecture 14: The environment model (cont.) Mutators for compound data ( Section 3.3, pages 251-273) Stack; Queue. Example: explaining make-counter. Counter: something which counts up from a number (define (make-counter n) (lambda () (set! n (+ n 1)) n) )

Télécharger la présentation

Example: explaining make-counter

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture 14:The environment model (cont.)Mutators for compound data (Section 3.3, pages 251-273)Stack; Queue

  2. Example: explaining make-counter • Counter: something which counts up from a number (define (make-counter n) (lambda () (set! n (+ n 1)) n) ) (define ca (make-counter 0))(ca) ==> 1(ca) ==> 2(define cb (make-counter 0))(cb) ==> 1(ca) ==> 3(cb) ==> 2

  3. make-counter: GE ca: E1 p: nb:(lambda () (set! n (+ n 1)) n) p: b:(set! n (+ n 1)) n (define ca (make-counter 0)) | GE n: 0 environment pointerpoints to E1because the lambdawas evaluated in E1 (lambda () (set! n (+ n 1)) n) | E1

  4. make-counter: GE ca: E1 1 n: 0 p: nb:(lambda () (set! n (+ n 1)) n) E2 p: b:(set! n (+ n 1)) n (ca) | GE ==> 1 empty (set! n (+ n 1)) | E2 n | E2 ==> 1

  5. make-counter: GE ca: E1 1 n: 0 p: nb:(lambda () (set! n (+ n 1)) n) 2 E3 p: b:(set! n (+ n 1)) n (ca) | GE ==> 2 empty (set! n (+ n 1)) | E3 n | E3 ==> 2

  6. make-counter: GE cb: ca: E1 E4 n: 2 p: nb:(lambda () (set! n (+ n 1)) n) E3 p: b:(set! n (+ n 1)) n p: b:(set! n (+ n 1)) n (define cb (make-counter 0)) | GE n: 0 (lambda () (set! n (+ n 1)) n) | E4

  7. make-counter: GE ca: cb: E1 E4 n: 2 n: 0 p: nb:(lambda () (set! n (+ n 1)) n) 1 E2 E5 p: b:(set! n (+ n 1)) n p: b:(set! n (+ n 1)) n (cb) | GE ==> 1

  8. make-counter: GE ca: cb: E1 E4 n: 2 n: 1 p: nb:(lambda () (set! n (+ n 1)) n) E2 p: b:(set! n (+ n 1)) n p: b:(set! n (+ n 1)) n Capturing state in local frames & procedures

  9. Lessons from the make-counter example • Environment diagrams get complicated very quickly • Rules are meant for the computer to follow, not to help humans • A lambda inside a procedure body captures theframe that was active when the lambda was evaluated • this effect can be used to store local state

  10. Lets do a message passing example (define (cons x y) (define (dispatch op) (cond ((eq? op 'car) x) ((eq? op 'cdr) y) (else (error "Unknown op -- CONS" op)))) dispatch) (define (car x) (x 'car)) (define (cdr x) (x 'cdr)) (define a (cons 1 2)) (car a)

  11. cons: car: cdr: p: x,y b:(def disp (op) .. dispatch) p: x b:(x ‘car) p: x b:(x ‘cdr) (define (cons x y) ..) | GE GE

  12. cons: car: p: x,y b:(def disp (op) .. dispatch) Disp: p: x b:(x ‘car) p: op b:(cond ..) (define a (cons 1 2)) | GE GE cdr: a: x: 1 Y: 2 E1 p: x b:(x ‘cdr)

  13. cons: car: x: p: x,y b:(def disp (op) .. dispatch) E2 Disp: p: x b:(x ‘car) p: op b:(cond ..) (car a) | GE GE cdr: a: x: 1 Y: 2 E1 p: x b:(x ‘cdr)

  14. cons: car: p: x,y b:(def disp (op) .. dispatch) Disp: p: x b:(x ‘car) empty E3 p: op b:(cond ..) (x ‘car) | E2 GE cdr: a: x: x: 1 Y: 2 E1 E2 p: x b:(x ‘cdr)

  15. cons: car: p: x,y b:(def disp (op) .. dispatch) Disp: p: x b:(x ‘car) p: op b:(cond ..) Returned value is x|E1=1.After that what remains is: GE cdr: a: x: 1 Y: 2 E1 p: x b:(x ‘cdr)

  16. Explaining Nested Definitions • Nested definitions : block structure (define (sqrt x) (define (good-enough? guess) (< (abs (- (square guess) x)) 0.001)) (define (improve guess) (average guess (/ x guess))) (define (sqrt-iter guess) (if (good-enough? guess) guess (sqrt-iter (improve guess)))) (sqrt-iter 1.0))

  17. sqrt: GE E1 x: 2 good-enough: improve: sqrt-iter: p: xb:(define good-enou ..) (define improve ..) (define sqrt-iter ..) (sqrt-iter 1.0) p: guessb:(< (abs ….) guess: 1 sqrt-iter guess: 1 The same x in all subprocedures good-enou? (sqrt 2) | GE

  18. Summary: The Environment Model • A precise, completely mechanical description of: • name-rule looking up the value of a variable • define-rule creating a new definition of a var • set!-rule changing the value of a variable • lambda-rule creating a procedure • application rule applying a procedure • You will use it to implement the Scheme interpreter, • Gotta practice using it… • It’s a major part of the final exam

  19. Mutators for compound data

  20. Mutating Compound Data • constructor: (cons x y) creates a new pair p • selectors: (car p) returns car part of pair (cdr p) returns cdr part of pair • mutators: (set-car! p new-x) changes car pointer in pair (set-cdr! p new-y) changes cdr pointer in pair ; Pair,anytype -> undef -- side-effect only!

  21. a X b red blue 10 Example: Pair/List Mutation (define a (list ‘red ‘blue)) (red blue) a ==> (define b a) b ==> (red blue) (set-car! a 10) a ==> (10 ‘blue) b ==> (10 ‘blue)

  22. d c X red blue 10 red blue Compare this with… (define c (list ‘red ‘blue)) (define d (list ‘red ‘blue)) c ==> (red blue) d ==> (red blue) (set-car! c 10) c ==> (10 blue) d ==> (red blue)

  23. c a d X X b red red blue blue 10 10 red blue Equivalent vs. The Same In the first example a and b are the same. A change to one changes the other. The point to a single object. In the second example c and d have at first the same value, but later on one changes and the other does not.They just happen to have at some point in time the same value.

  24. Eq? vs. Equal? • To check whether two names point to the same object: Test witheq? (eq? a b) ==> #t • To check whether two elements currently have the same content: Test withequal? (equal? (list 1 2) (list 1 2)) ==> #t(eq? (list 1 2) (list 1 2)) ==> #f

  25. Q&A: “2 B 2 B =” Q: If we change an object, is it the same object? A: Yes, if we retain the same pointer to the object. Q: How can we tell if two elements share the same object? A. One thing you can do is mutate one and see if the other also changes.

  26. x a b 1 2 Example 2: Pair/List Mutation (define x (list 'a 'b)) (set-car! (cdr x) (list 1 2)) • Eval (cdr x) to get a pair object • Change car pointer of that pair object (a ( 1 2))

  27. x X 3 4 y X X 7 1 2 Your Turn x ==> (3 4) y ==> (1 2) (set-car! x y) x ==> (set-cdr! y (cdr x)) x ==> (set-cdr! x (list 7) x ==> ((1 2) 4) ((1 4) 4) ((1 4) 7)

  28. Summary • Scheme provides built-in mutators • set! to change a binding • set-car! and set-cdr! to change a pair • Mutation introduces substantial complexity • Unexpected side effects • Substitution model is no longer sufficient to explain behavior

  29. Stack

  30. Stack Data Abstraction • constructor:(make-stack) returns an empty stack • selectors:(top stack) returns current top element from a stack • operations:(insert stack elem) returns a new stack with the element added to the top of the stack (delete stack) returns a new stack with the top element removed from the stack (empty-stack? stack) returns #t if no elements, #f otherwise

  31. Insert Insert Insert Stack Data Abstraction Last in, First out. Insert Delete

  32. Stack Contract • If s is a stack, created by (make-stack)and subsequent stack procedures, where i is the number of insertions and d is the number of deletions, then • If d>i then it is an error • If d=i then (empty-stack? s) is true, and (top s) and (delete s) are errors. • If d<i then (empty-stack? s) is false and(top (delete (insert s val))) = (top s) • If d<=i then (top (insert s val)) = val for any val

  33. Stack Implementation Strategy • implement a stack as a list a b d • we will insert and delete items at the front of the stack

  34. Stack Implementation (define (make-stack) nil) (define (empty-stack? stack) (null? stack)) (define (insert stack elem) (cons elem stack)) (define (delete stack) (if (empty-stack? stack) (error "stack underflow – delete") (cdr stack))) (define (top stack) (if (empty-stack? stack) (error "stack underflow – top") (car stack)))

  35. Limitations in our Stack • Stack does not have identity (define s (make-stack)) s ==> () (insert s 'a) ==> (a) s ==> () (set! s (insert s 'b)) s ==> (b)

  36. (delete! s) s X d c a stack Alternative Stack Implementation • The data type contains a list of elements – as before. • Insert and delete mutate a stack object. • The first element of the list is special to distinguish Stack objects from other lists – defensive programming The stack will be a mutable data type.

  37. (define (make-stack) (cons 'stack nil)) Alternative Stack Implementation (1) (define (stack? stack) (and (pair? stack) (eq? 'stack (car stack)))) (define (empty-stack? stack) (if (not (stack? stack)) (error "object not a stack:" stack) (null? (cdr stack)))) (define (top stack) (if (empty-stack? stack) (error "stack underflow – top") (cadr stack)))

  38. Alternative Stack Implementation (2) (define (insert! stack elem) (cond ((not (stack? stack)) (error "object not a stack:" stack)) (else (set-cdr! stack (cons elem (cdr stack))) stack))) (define (delete! stack) (if (empty-stack? stack) (error "stack underflow – delete") (set-cdr! stack (cddr stack))) stack)

  39. Does the user have to know about it? Usually the user does not care about the implementation As long as the contract is being kept. Both implementations keep the contract. Yet: This is a change to the abstraction! The user should know if the object mutates or not in order to use the abstraction correctly. If we (define a b), can a later change because of changes to b?

More Related