1/32 Data Mutation Primitive and compound data mutators set! for names set-car!, set-cdr! for pairs Stack example non-mutating mutating Queue example non-mutating.

Slides:



Advertisements
Similar presentations
Stacks, Queues, and Linked Lists
Advertisements

1 Lecture 16: Tables and OOP. 2 Tables -- get and put.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
מבוא מורחב למדעי המחשב תרגול 14. Serial Programming Expressions are evaluated in a well-known order One expression at a time Life are easy (though slow)
מבוא מורחב 1 Lecture #7. מבוא מורחב 2 The rational number abstraction Wishful thinking: (make-rat ) Creates a rational number (numer ) Returns the numerator.
1-1 An Introduction to Scheme March Introduction A mid-1970s dialect of LISP, designed to be a cleaner, more modern, and simpler version than.
Fall 2008Programming Development Techniques 1 Topic 19 Mutable Data Objects Section 3.3.
CS 106 Introduction to Computer Science I 12 / 06 / 2006 Instructor: Michael Eckmann.
SICP Symbolic data Symbol: a primitive type Generalization Symbolic differentiation.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 11. Dotted tail notation (define (proc m1 m2. opt) ) Mandatory Arguments: m1, m2 Mandatory Arguments: m1, m2.
Data Abstraction… The truth comes out…. What we’re doing today… Abstraction ADT: Dotted Pair ADT: List Box and Pointer List Recursion Deep List Recursion.
ISBN Chapter 15 Functional Programming Languages Mathematical Functions Fundamentals of Functional Programming Languages Introduction to.
SICP Data Mutation Primitive and Compound Data Mutators Stack Example non-mutating mutating Queue Example non-mutating mutating.
Mutation So far, our data abstractions consists of the following: –Constructors –Selectors/Accessors –Operations –Contract Once a data object is created,
( (lambda (z) (define x (lambda (x) (lambda (y z) (y x)))) ( ( (x (lambda () z)) (lambda (z) z) 3 ) ) ) 2)
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
1 Lecture 15: More about assignment and the Environment Model (EM)
Stacks, Queues, and Deques
1 Lecture OO, the notion of inheritance 3 Stacks in OO style (define (make-stack) (let ((top-ptr '())) (define (empty?) (null? top-ptr)) (define.
ISBN Chapter 15 Functional Programming Languages.
Functional Programming Universitatea Politehnica Bucuresti Adina Magda Florea
COP4020 Programming Languages Functional Programming Prof. Xin Yuan.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
1 Data abstraction, revisited Design tradeoffs: Speed vs robustness modularity ease of maintenance Table abstract data type: 3 versions No implementation.
מבוא מורחב 1 Lecture #9. מבוא מורחב 2 Symbol: a primitive type constructors: (quote alpha) ==> quote is a special form. One argument: a name. selectors.
CS1101S Lecture 14: Environment Model & Mutable Data 10 October 2012.
6.001 SICP 1/ SICP Object Oriented Programming Data Abstraction using Procedures with State Message-Passing Object Oriented Modeling Class diagrams.
1 Lecture 14: Assignment and the Environment Model (EM)
SICP Object Oriented Programming Data Abstraction using Procedures with State Message-Passing Object Oriented Modeling Class diagrams Instance.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
1 Vectors, binary search, and sorting. 2 We know about lists O(n) time to get the n-th item. Consecutive cons cell are not necessarily consecutive in.
CS 152: Programming Language Paradigms February 12 Class Meeting Department of Computer Science San Jose State University Spring 2014 Instructor: Ron Mak.
Abstraction A way of managing complexity for large programs A means of separating details of computation from use of computation Types of Abstraction Data.
Abstract Syntax cs7100 (Prasad) L7AST.
Edited by Original material by Eric Grimson
Pairs and Lists. Data Abstraction. SICP: Sections – 2.2.1
6.001 SICP Object Oriented Programming
CS 1114: Implementing Search
The role of abstractions
Lecture 14 - Environment Model (cont.) - Mutation - Stacks and Queues
Lists in Lisp and Scheme
COP4020 Programming Languages
Env. Model Implementation
6.001 SICP Data abstractions
The Metacircular Evaluator
Lecture 15: Tables and OOP
The Metacircular Evaluator
Lecture 16: Tables and OOP
The Metacircular Evaluator (Continued)
6.001 SICP Further Variations on a Scheme
Mutable Data (define mylist (list 1 2 3)) (bind ((new (list 4)))
Lecture #9 מבוא מורחב.
Abstract Syntax cs7100 (Prasad) L7AST.
Lecture 12: Message passing The Environment Model
Lecture 13 - Assignment and the environments model Chapter 3
Data Mutation Primitive and compound data mutators set! for names
Lecture 14 - Environment Model (cont.) - Mutation - Stacks and Queues
topics mutable data structures
6.001 SICP Variations on a Scheme
Mutators for compound data Stack Queue
6.001 SICP Data Mutation Primitive and Compound Data Mutators
Lecture 14: The environment model (cont
6.001 SICP Data abstractions
Lecture #7 מבוא מורחב.
Today’s topics Abstractions Procedural Data
6.001 SICP Interpretation Parts of an interpreter
Lecture 13: Assignment and the Environment Model (EM)
More Scheme CS 331.
Presentation transcript:

1/32 Data Mutation Primitive and compound data mutators set! for names set-car!, set-cdr! for pairs Stack example non-mutating mutating Queue example non-mutating mutating

2/32 A data abstraction consists of: constructors selectors mutators operations contract Elements of a Data Abstraction -- makes a new structure -- changes an existing structure

3/32 Primitive Data (define x 10) creates a new binding for name; special form x returns value bound to name To Mutate: (set! x "foo") changes the binding for name; special form (value is undefined)

4/32 Assignment -- set! Substitution model -- functional programming: (define x 10) (+ x 5) ==> 15 - expression has same value... each time it evaluated (in (+ x 5) ==> 15 same scope as binding) With mutation: (define x 10) (+ x 5) ==> 15 - expression "value" depends... on when it is evaluated (set! x 94)... (+ x 5) ==> 99

5/32 Compound Data constructor: (cons x y) creates a new pair p selectors: (car p) returns car part of pair p (cdr p) returns cdr part of pair p mutators: (set-car! p new-x) changes car part of pair p (set-cdr! p new-y) changes cdr part of pair p ; Pair,anytype -> undef -- side-effect only!

6/32 Example 1: Pair/List Mutation (define a (list 1 2)) (define b a) a  (1 2) b  (1 2) 12 b a (set-car! a 10) b  (10 2) 10 X Compare with: (define a (list 1 2)) (define b (list 1 2)) 12 a 12 b 10 X (set-car! a 10) b  (1 2)

7/32 Example 2: Pair/List Mutation (define x (list 'a 'b)) ab x X 21 (set-car! (cdr x) (list 1 2)) 1.Evaluate (cdr x) to get a pair object 2.Change car part of that pair object How can we use mutation to achieve the result at right?

8/32 Sharing, Equivalence and Identity How can we tell if two things are equivalent? -- Well, what do you mean by "equivalent"? 1.The same object: test with eq? (eq? a b) ==> #t 2.Objects that "look" the same: test with equal? (equal? (list 1 2) (list 1 2)) ==> #t (eq? (list 1 2) (list 1 2)) ==> #f 1212 (1 2) 12 b a

9/32 Sharing, Equivalence and Identity How can we tell if two things are equivalent? -- Well, what do you mean by "equivalent"? 1.The same object: test with eq? (eq? a b) ==> #t 2.Objects that "look" the same: test with equal? (equal? (list 1 2) (list 1 2)) ==> #t (eq? (list 1 2) (list 1 2)) ==> #f If we change an object, is it the same object? -- Yes, if we retain the same pointer to the object How tell if part of an object is shared with another? -- If we mutate one, see if the other also changes

10/32 x ==> (3 4) y ==> (1 2) (set-car! x y) x ==> followed by (set-cdr! y (cdr x)) x ==> Your Turn 34 x 12 y ((1 2) 4) X ((1 4) 4) X 34 x 12 y

11/32 End of part 1 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

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

13/32 Stack Contract If s is a stack, created by (make-stack) and subsequent stack procedures, where i is the number of inserts and j is the number of deletes, then 1.If j>i then it is an error 2.If j=i then (empty-stack? s) is true, and (top-stack s) is an error. 3.If j<i then (empty-stack? s) is false, and for any val, (top-stack (delete-stack (insert-stack s val))) = (top-stack s) 4.If j<=i then for any val, (top-stack (insert-stack s val))) = val

14/32 Stack Implementation Strategy implement a stack as a list dba we will insert and delete items at the front of the list

15/32 Stack Implementation ; Stack = List (define (make-stack) '()) (define (empty-stack? s) ; Stack -> boolean (null? s)) (define (insert-stack s elt) ; Stack, A -> Stack (cons elt s)) (define (delete-stack s) ; Stack -> Stack (if (not (empty-stack? s)) (cdr s) (error "stack underflow – delete")) (define (top-stack s) ; Stack -> A (if (not (empty-stack? s)) (car s) (error "stack underflow – top")))

16/32 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)

17/32 Attach a type tag – defensive programming Additional benefit: Provides an object whose identity remains even as the object mutates Alternative Stack Implementation – pg. 1 Note: This is a change to the abstraction! User should know if the object mutates or not in order to use the abstraction correctly. acd stack s X (delete! s)

18/32 Alternative Stack Implementation – pg. 2 ; Stack = Pair > (define (make-stack) (cons 'stack '())) (define (stack? s) ; anytype -> boolean (and (pair? s) (eq? 'stack (car s)))) (define (empty-stack? s) ; Stack -> boolean (if (stack? s) (null? (cdr s)) (error "object not a stack:" s)))

19/32 Alternative Stack Implementation – pg. 3 (define (insert-stack! s elt); Stack, A -> Stack (if (stack? s) (set-cdr! s (cons elt (cdr s))) (error "object not a stack:" s) stack) (define (delete-stack! s) ; Stack -> Stack (if (not (empty-stack? s)) (set-cdr! s (cddr s)) (error "stack underflow – delete")) stack) (define (top-stack s) ; Stack -> A (if (not (empty-stack? s)) (cadr s) (error "stack underflow – top")))

20/32 Queue Data Abstraction (Non-Mutating) constructor: (make-queue) returns an empty queue accessors: (front-queue q) returns the object at the front of the queue. If queue is empty signals error operations: (insert-queue q elt) returns a new queue with elt at the rear of the queue (delete-queue q) returns a new queue with the item at the front of the queue removed (empty-queue? q) tests if the queue is empty

21/32 Queue Contract If q is a queue, created by (make-queue) and subsequent queue procedures, where i is the number of inserts, and j is the number of deletes 1.If j>i then it is an error 2.If j=i then (empty-queue? q) is true, and (front-queue q) is an error 3.If j<i then (empty-queue? q) is false, and (front-queue q) is the (j+1)st element inserted into the queue

22/32 Simple Queue Implementation – pg. 1 Let the queue simply be a list of queue elements: cdb The front of the queue is the first element in the list To insert an element at the tail of the queue, we need to “copy” the existing queue onto the front of the new element: dnewcb

23/32 Simple Queue Implementation – pg. 2 (define (make-queue) '()) (define (empty-queue? q) (null? q)) ; Queue -> boolean (define (front-queue q) ; Queue -> A (if (not (empty-queue? q)) (car q) (error "front of empty queue:" q))) (define (delete-queue q) ; Queue -> Queue (if (not (empty-queue? q)) (cdr q) (error "delete of empty queue:" q))) (define (insert-queue q elt) ; Queue, A -> Queue (if (empty-queue? q) (cons elt '()) (cons (car q) (insert-queue (cdr q) elt))))

24/32 Simple Queue - Orders of Growth How efficient is the simple queue 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) =  (1) that is, constant in time Space: S(n) =  (1) that is, constant in space insert-queue: Time: T(n) =  (n) that is, linear in time Space: S(n) =  (n) that is, linear in space

25/32 Queue Data Abstraction (Mutating) constructor: (make-queue) returns an empty queue accessors: (front-queue q) returns the object at the front of the queue. If queue is empty signals error mutators: (insert-queue! q elt) inserts the elt at the rear of the queue and returns the modified queue (delete-queue! q) removes the elt at the front of the queue and returns the modified queue operations: (queue? q) tests if the object is a queue (empty-queue? q) tests if the queue is empty

26/32 Better Queue Implementation – pg. 1 We’ll attach a type tag as a defensive measure 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 queue cdba front-ptr rear-ptr

27/32 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)) queue cdba front-ptr rear-ptr

28/32 Better Queue Implementation – pg. 2 (define (make-queue) (cons 'queue (cons '() '()))) (define (queue? q) ; anytype -> boolean (and (pair? q) (eq? 'queue (car q)))) (define (empty-queue? q) ; Queue -> boolean (if (queue? q) (null? (front-ptr q)) (error "object not a queue:" q))) (define (front-queue q) ; Queue -> A (if (not (empty-queue? q)) (car (front-ptr q)) (error "front of empty queue:" q)))

29/32 Queue Implementation – pg. 3 (define (insert-queue! q elt); Queue, A -> Queue (let ((new-pair (cons elt '()))) (cond ((empty-queue? q) (set-front-ptr! q new-pair) (set-rear-ptr! q new-pair)) (else (set-cdr! (rear-ptr q) new-pair) (set-rear-ptr! q new-pair))) q))) queue cdba front-ptr rear-ptr e

30/32 Queue Implementation – pg. 4 (define (delete-queue! q) ; Queue -> Queue (if (not (empty-queue? q)) (set-front-ptr! q (cdr (front-ptr q))) (error "delete of empty queue:" q)) q) queue cdba front-ptr rear-ptr

31/32 Mutating Queue - Orders of Growth How efficient is the mutating queue 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) = O(1) that is, constant in time Space: S(n) = O(1) that is, constant in space insert-queue!: Time: T(n) = O(1) that is, constant in time Space: S(n) = O(1) that is, constant in space

32/32 Summary Built-in mutators which operate by side-effect set! (special form) set-car! ; Pair, anytype -> undef set-cdr! ; Pair, anytype -> undef Extend our notion of data abstraction to include mutators Mutation is a powerful idea enables new and efficient data structures can have surprising side effects breaks our model of "functional" programming (substitution model)