Environment Model cont' - PowerPoint PPT Presentation

1 / 52
About This Presentation
Title:

Environment Model cont'

Description:

set-car! and set-cdr! are procedures, while set! is a special form ... Compare this with... (define c (list red blue)) (define d (list red blue)) (set-car! ... – PowerPoint PPT presentation

Number of Views:19
Avg rating:3.0/5.0
Slides: 53
Provided by: haimk
Category:

less

Transcript and Presenter's Notes

Title: Environment Model cont'


1
Lecture 14
- Environment Model (cont.) - Mutation- Stacks
and Queues
2
Example explaining make-counter
  • Counter something which counts up from a number
  • (define make-counter (lambda (n) (lambda
    () (set! n ( n 1)) n )))
  • (define ca (make-counter 0))(ca) gt 1(ca) gt
    2(define cb (make-counter 0))(cb) gt 1(ca)
    gt 3(cb) gt 2

2
3
(define ca (make-counter 0)) GE
n 0
environment pointerpoints to E1because the
lambdawas evaluated in E1
(lambda () (set! n ( n 1)) n) E1
3
4
(ca) GE
gt 1
empty
(set! n ( n 1)) E2
n E2 gt 1
4
5
(ca) GE
gt 2
empty
(set! n ( n 1)) E3
n E3 gt 2
5
6
(define cb (make-counter 0)) GE
n 0
(lambda () (set! n ( n 1)) n) E4
6
7
(cb) GE
gt 1
7
8
Capturing state in local frames procedures
8
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

9
10
Explaining Nested Definitions
  • Nested definitions block structure
  • (define (sqrt x)
  • (define (good-enough? guess)
  • (lt (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))

???? ????? - ????? 13
10
11
(sqrt 2) GE
guess 1
sqrt-iter
guess 1
good-enou?
???? ????? - ????? 13
11
12
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)
???? ????? - ????? 13
12
13
(define a (cons 1 2)) GE
car
cdr
a
p xb(x car)
p xb(x cdr)
???? ????? - ????? 13
13
14
(car a) GE
gt 1
car
cdr
a
E1
x 1 y 2
p xb(x car)
p xb(x cdr)
dispatch
(x car) E2
???? ????? - ????? 13
(cond ..) E3 gt 1
14
15
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 pai
  • 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!

set-car! and set-cdr! are procedures, while set!
is a special form
16
Example Pair/List Mutation
  • (define a (list red blue))

(red blue)
a gt
(define b a)
b gt
(red blue)
(set-car! a 10)
a gt
(10 blue)
b gt
(10 blue)
17
Compare this with
  • (define c (list red blue))
  • (define d (list red blue))

c gt
(red blue)
d gt
(red blue)
(set-car! c 10)
(10 blue)
c gt
d gt
(red blue)
18
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.
Without mutation, there is no identity equality
of value is all we have
19
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

X
(a ( 1 2))
20
Can create cyclic structures
  • (define x (list 1 2))

(cddr x) gt ()
(set-cdr! (cdr x) x)
(caddr x) gt 1
  • Beware of infinite scanning (or printing).
  • Dr. Scheme prevents the infinite printing of
    returned values (sometimes). Prints some
    indication
  • x gt 0(1 2 . 0)

21
Eq? vs. Equal?
  • To check whether two names point to the same
    object
  • Test with eq?
  • (eq? a b) gt t
  • To check whether two elements currently have the
    same content
  • Test with equal?
  • (equal? (list 1 2) (list 1 2)) gt t(eq?
    (list 1 2) (list 1 2)) gt f

22
Lets go over the following
  • x gt (3 4)
  • y gt (1 2)
  • (set-car! x y)
  • x gt
  • (set-cdr! y (cdr x))
  • x gt
  • (set-cdr! x (list 7)
  • x gt

((1 2) 4)
((1 4) 4)
((1 4) 7)
23
We can actually get away only with set!
  • (define (cons x y)
  • (define (change-car val) (set! x val))
  • (define (change-cdr val) (set! y val))
  • (lambda (m)
  • (cond
  • ((eq? m 'car) x)
  • ((eq? m 'cdr) y)
  • ((eq? m 'set-car!) change-car)
  • ((eq? m 'set-cdr!) change-cdr)
  • (else
  • (error "Undefined operation m)))))

24
We can actually get away only with set!
  • (define (car z) (z 'car))
  • (define (cdr z) (z 'cdr))
  • (define (set-car! z new-value)
  • ((z 'set-car!) new-value)
  • z)
  • (define (set-cdr! z new-value)
  • ((z 'set-cdr!) new-value)
  • z)
  • Saw that pairs can be implemented with functions.
  • Now we see that pair mutation can be implemented
    with functions and set!
  • But set! is an essential addition.

25
Another mutation example count-pairs
We want to count the number of pairs in a
list-structure
(define (count-pairs p) (if (not (pair? p))
0 ______________________________
____ __________________________________)
)
( (count-pairs (car p)) (count-pairs (cdr
p)) 1 )
26
Mutation example count-pairs (contd)
gt (count-pairs (1 (2 3) 4)) 5 gt (count-pairs
(cons 1 (cons 2 3)) 2 gt (define l (1 2 3)) gt
(set-cdr! (cdr (cdr l)) l)
gt (count-pairs l) Time to drink a LONG espresso
27
count-pairs improved version
(define (count-pairs1 p) (let ((pairs-list
null)) (define (cp-helper x) (cond
((not (pair? x) __________)
(___________________ 0) (else
______________________________
_______________________
_______________________)))
(cp-helper p)))
0
(memq x pairs-list)
(set! pairs-list (cons x pairs-list))
( (cp-helper (car x)) (cp-helper (cdr x))
1)
28
Stack Data Abstraction
Last in, First out.
Insert
Delete
29
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 (push)
  • (delete stack) returns a new stack with the
    top element removed from the stack (pop)
  • (empty-stack? stack) returns t if no elements,
    f otherwise
  • contract
  • (delete stack) require (not (empty-stack? stack))
  • (top stack) require (not (empty-stack? stack))
  • ensure (equal? (delete (insert stack elem))
    stack)
  • ensure (equal? (top (insert stack elem)) elem)

30
Stack Implementation Strategy
  • implement a stack as a list

d
b
a
  • we will insert and delete items at the front of
    the stack

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

32
Limitations in our Stack
  • Stack does not have identity
  • (define s (make-stack))
  • s gt ()
  • (insert s 'a) gt (a)
  • s gt ()
  • (set! s (insert s 'b))
  • s gt (b)

33
Mutable Stack Implementation
The stack will be a mutable data type.
  • 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

34
Mutable Stack Data Abstraction
  • constructor (make-stack) returns an empty
    stack
  • queries (selectors) (top stack) returns
    current top element from a stack (empty-stack?
    stack) returns t if no elements, f otherwise
  • (stack? any) returns t if any is a
    stack, f otherwise
  • command (mutators, transformers) (insert!
    stack elem) modify the stack by adding
    elem to the top of the stack (push)
  • (delete! stack) modify the stack by removing
    the top element from the stack (pop)

stack? is really not part of the stack abstraction
35
Mutable Stack Implementation (1)
  • (define (make-stack) (cons 'stack nil))

(define (stack? stack) (and (pair? stack) (eq?
'stack (car stack))))
(define (empty-stack? stack) (null? (cdr
stack)))
(define (top stack) (if (empty-stack? stack)
(error "stack underflow top") (cadr
stack)))
36
Mutable Stack Implementation (2)
  • (define (insert! stack elem)
  • (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)

Here the mutators return the stack. May choose to
return a neutral value, eg. ok or nothing (more
later)
37
Mutatable vs. functional
  • The decision between a mutable stack and a
    functional stack is part of the contract
  • Changing this changes the abstraction!
  • The user should know if the object mutates or not
    in order to use the abstraction correctly
  • For example, if we write
  • (define stack1 stack2)
  • can stack1 later change because of changes to
    stack2 ?

38
A Queue
FIFO First In, First Out
39
A Queue
Insert
Insert
FIFO First In, First Out
Insert
x3
x2
Delete
40
A Queue Implementation
  • A queue is a list of queue elements
  • The front of the queue is the first element in
    the list
  • To insert an element at the tail of the queue,
    need to scan the entire list, then attach the new
    element at the rear

d
new
c
b
41
A Queue Implementation (Cont)
  • (define (make-queue) null)
  • (define (empty-queue? q) (null? q))
  • (define (front-queue q)
  • (if (empty-queue? q)
  • (error "front of empty queue" q)
  • (car q)))
  • (define (delete-queue q)
  • (if (empty-queue? q)
  • (error "delete of empty queue" q)
  • (cdr q)))
  • (define (insert-queue q elt)
  • (if (empty-queue? q)
  • (cons elt nil)
  • (cons (car q) (insert-queue (cdr q) elt))))

42
Complexity of the implementation
  • For a queue of length n
  • Time required -- number of cons, car, cdr calls?
  • Space required -- number of new cons cells?
  • front-queue, delete-queue
  • Time T(n) T(1) that is, constant in time
  • Space S(n) T(1) that is, constant in space
  • insert-queue
  • Time T(n) T (n) that is, linear in time
  • Space S(n) T(n) that is, linear in space

43
A more efficient implementation
  • In order to make both insert and delete efficient
  • we need constant time access to the front and the
    rear of the queue.
  • we can achieve this if we keep a pointer to the
    front and the rear of the queue.
  • A mutable implementation.

44
Mutable Queue Data Abstraction
  • constructor (make-queue) returns an empty
    queue
  • queries (selectors, assessors)
  • (front-queue q) returns the object at the
    front of the queue. If queue is empty
    signals error
  • (empty-queue? q) tests if the queue is empty
  • commands (mutators, transformers)
    (insert-queue! q elt) inserts the elt at the
    rear of the queue and returns ok
  • (delete-queue! q) removes the elt at the front
    of the queue and returns ok
  • additional query
  • (queue? q) tests if the object is a queue

45
Implementation
  • We attach a type tag as before.
  • Maintain queue identity
  • Build a structure to hold
  • a list of items in the queue
  • a pointer to the front of the queue
  • a pointer to the rear of the queue

46
Queue Helper Procedures
  • Hidden inside the abstraction
  • (define (front-ptr q) (cadr q))
  • (define (rear-ptr q) (cddr q))
  • (define (set-front-ptr! q item)
  • (set-car! (cdr q) item))
  • (define (set-rear-ptr! q item)
  • (set-cdr! (cdr q) item))

47
Queue implementation
  • (define (make-queue)
  • (cons 'queue (cons null null)))
  • (define (queue? q)
  • (and (pair? q) (eq? 'queue (car q))))
  • (define (empty-queue? q)
  • (if (not (queue? q))
  • (error "object not a queue" q)
  • (null? (front-ptr q))))
  • (define (front-queue q)
  • (if (empty-queue? q)
  • (error "front of empty queue" q)
  • (car (front-ptr q))))

48
Queue implementation Insert
  • (define (insert-queue! q elt)
  • (let ((new-pair (cons elt nil)))
  • (cond ((empty-queue? q)
  • (set-front-ptr! q new-pair)
  • (set-rear-ptr! q new-pair)
  • ok)
  • (else
  • (set-cdr! (rear-ptr q) new-pair)
  • (set-rear-ptr! q new-pair)
  • ok))))

49
Queue implementation - delete
  • (define (delete-queue! q)
  • (cond ((empty-queue? q)
  • (error "delete of empty queue" q))
  • (else
  • (set-front-ptr! q (cdr (front-ptr q)))
  • ok)))

50
Time and Space complexities ?
O(1)
51
Programming Styles Procedural vs.
Object-Oriented
  • Procedural programming - Organize system around
    procedures that operate on data
  • (do-something ltdatagt ltarggt ...)
  • (do-another-thing ltdatagt)
  • Object-based programming - Organize system
    around objects that receive messages
  • ((ltobjectgt 'do-something) ltarggt)
  • ((ltobjectgt 'do-another-thing) ... )
  • An object encapsulates data and operations
  • Message passing and returned procedures are
    the means to write object oriented code in scheme

52
Stacks in OO style
(define (make-stack) (let ((top-ptr '()))
(define (empty?) (null? top-ptr)) (define
(delete!) (if (null? top-ptr)
(error . . .) (set! top-ptr (cdr
top-ptr))) top-ptr ) (define (insert!
elmt) (set! top-ptr (cons elmt top-ptr))
top-ptr) (define (top) (if (null?
top-ptr) (error . . .) (car
top-ptr))) (define (dispatch op) (cond
((eq? op 'empty?) empty?) ((eq? op 'top)
top) ((eq? op 'insert!) insert!)
((eq? op 'delete!) delete!))) dispatch))
53
Stacks in OO style
(define s (make-stack)) ((s 'insert!) 'a)
gt ((s 'insert!) 'b) gt ((s 'top)) gt ((s
'delete!)) gt ((s 'top)) gt ((s 'delete!)) gt
(a)
(b a)
b
(a)
a
()
  • compare with message passing examples in OO we
    do not hide behind a functional layer eg.
  • (define (insert! s a) ((s insert!) a))
  • In OO programming languages the notation is eg.
  • s.insert(a)
  • s.delete()
Write a Comment
User Comments (0)
About PowerShow.com