Pairs and Lists. Data Abstraction. SICP: Sections – 2.2.1

Slides:



Advertisements
Similar presentations
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 5. 2 List Utilities Scheme built-in procedures –(list x y z...) –(list-ref lst index) –(length lst) –(append.
Advertisements

Lists in Lisp and Scheme a. Lists are Lisp’s fundamental data structures, but there are others – Arrays, characters, strings, etc. – Common Lisp has moved.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Chapter 3 Functional Programming. Outline Introduction to functional programming Scheme: an untyped functional programming language.
מבוא מורחב 1 Lecture #7. מבוא מורחב 2 The rational number abstraction Wishful thinking: (make-rat ) Creates a rational number (numer ) Returns the numerator.
מבוא מורחב 1 Lecture #6. מבוא מורחב 2 Primality testing (application) Know how to test whether n is prime in  (log n) time => Can easily find very large.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 7. Data directed programming Section 2.4, pages ,2.5.2 pages (but with a different example)
מבוא מורחב - שיעור 10 1 Symbols Manipulating lists and trees of symbols: symbolic differentiation Lecture 10.
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.
6.001 SICP SICP – September ? 6001-Introduction Trevor Darrell 32-D web page: section.
6.001 SICP SICP Sections 5 & 6 – Oct 5, 2001 Quote & symbols Equality Quiz.
מבוא מורחב - שיעור 2 1 Lecture 2 - Substitution Model (continued) - Recursion - Block structure and scope (if time permits)
מבוא מורחב - שיעור 81 Lecture 8 Lists and list operations (continue).
מבוא מורחב - שיעור 12 1 Lecture 12 Data directed programming Message passing dotted-tail notation & apply Section 2.4, pages ,2.5.2 pages.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 10. Data directed programming Message passing Section 2.4, pages ,2.5.2 pages (but with.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 7. Outline Symbols Data Directed Programming, Message Passing.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
PPL Pairs, lists and data abstraction. Data Abstraction? An interface: separate implementation from usage Think of the Map interface in Java: we know.
PPL Pairs, lists and data abstraction. Compound Data Until now: atomic, unrelated entities Now: organized into structures Why? – Better conceptual level.
Spring 2008Programming Development Techniques 1 Topic 6 Hierarchical Data and the Closure Property Section September 2008.
1 Append: process  (append list1 list2) (cons 1 (append ‘(2) list2)) (cons 1 (cons 2 (append ‘() list2))) (cons 1 (cons 2 list2)) (define (append list1.
Today’s topic: Abstraction Compound Data Data Abstractions: Isolate use of data abstraction from details of implementation Relationship between data abstraction.
מבוא מורחב 1 Lecture #9. מבוא מורחב 2 Symbol: a primitive type constructors: (quote alpha) ==> quote is a special form. One argument: a name. selectors.
Fall 2008Programming Development Techniques 1 Topic 5 Data Abstraction Note: This represents a change in order. We are skipping to chapter 2 without finishing.
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
1 Data Abstraction. Pairs and Lists. (SICP Sections – 2.2.1)
מבוא מורחב שיעור 7 1 Lecture 7 Data Abstraction. Pairs and Lists. (Sections – 2.2.1)
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.
CS314 – Section 5 Recitation 10
Basic Scheme February 8, 2007 Compound expressions Rules of evaluation
Edited by Original material by Eric Grimson
Tagged Data Tag: a symbol in a data structure that identifies its type
Lecture 16 Streams continue Infinite Streams מבוא מורחב - שיעור 16.
6.001 Jeopardy.
6.001 SICP Object Oriented Programming
Chapter 15 – Functional Programming Languages
Lecture 14 - Environment Model (cont.) - Mutation - Stacks and Queues
Lists in Lisp and Scheme
Env. Model Implementation
6.001 SICP Data abstractions
The Metacircular Evaluator
Lecture 18 Infinite Streams and
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
Lecture #6 section pages pages72-77
Lecture #6 מבוא מורחב.
The Metacircular Evaluator (Continued)
6.001 SICP Further Variations on a Scheme
Lecture #9 מבוא מורחב.
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 #6 section pages pages72-77
6.001 SICP Variations on a Scheme
6.001 SICP Data Mutation Primitive and Compound Data Mutators
Lecture 14: The environment model (cont
6.001 SICP Data abstractions
Announcements Quiz 5 HW6 due October 23
Lecture #7 מבוא מורחב.
List and list operations (continue).
6.001: Structure and Interpretation of Computer Programs
Today’s topics Abstractions Procedural Data
Lecture 2 מבוא מורחב.
6.001 SICP Interpretation Parts of an interpreter
Lecture # , , , , מבוא מורחב.
Introduction to the Lab
Lecture 2 מבוא מורחב.
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
More Scheme CS 331.
Presentation transcript:

Pairs and Lists. Data Abstraction. SICP: Sections 2.1.1 – 2.2.1 Lecture notes: Chapter 3

Box and Pointer Diagram 2 1 a (define a (cons 1 2)) A pair can be implemented directly using two “pointers”. Originally on IBM 704: (car a) Contents of Address part of Register (cdr a) Contents of Decrement part of Register

Pair: A primitive data type. Constructor: (cons a b) Selectors: (car p) (cdr p) Guarantee: (car (cons a b)) = a (cdr (cons a b)) = b Abstraction barrier: We say nothing about the representation or implementation of pairs.

Pairs (define x (cons 1 2)) (define y (cons 3 4)) (define z (cons x y)) (car (car z))  1 ;(caar z) (car (cdr z))  3 ;(cadr z)

Box and pointer diagrams (cons (cons 1 (cons 2 3)) 4) 4 1 3 2

Compound Data A closure property: The result obtained by creating a compound data structure can itself be treated as a primitive object and thus be input to the creation of another compound object. Pairs have the closure property: We can pair pairs, pairs of pairs etc. (cons (cons 1 2) 3) 3 2 1

The empty list (a.k.a. null or nill) Lists The empty list (a.k.a. null or nill) (cons 1 (cons 3 (cons 2 ’() ))) 1 3 2 List are the glue for putting together many values just as pairs are the glue for pairs of values. Syntactic sugar: (list 1 3 2)

Formal Definition of a List A list is either ’() -- The empty list A pair whose cdr is a list. Lists are closed under the operations cons and cdr: If lst is a non-empty list, then (cdr lst) is a list. If lst is a list and x is arbitrary, then (cons x lst) is a list. מבוא מורחב שיעור 7

(cons <x1> (cons <x2> ( … (cons <xn> ’() )))) Lists (list <x1> <x2> ... <xn>) is syntactic sugar for (cons <x1> (cons <x2> ( … (cons <xn> ’() )))) <x1> <x2> <xn> …

Lists (examples) The following expressions all result in the same structure: (cons 3 (list 1 2)) (cons 3 (cons 1 (cons 2 ’() ))) (list 3 1 2) 3 1 2 and similarly the following (cdr (list 1 2 3)) (cdr (cons 1 (cons 2 (cons 3 ’() )))) (cons 2 (cons 3 ’() )) (list 2 3) 2 3

More Elaborate Lists (list 1 2 3 4) Value:(1 2 3 4) (cons (list 1 2) (list 3 4)) (list (list 1 2) (list 3 4)) Value:(1 2 3 4) Value:((1 2) 3 4) Value:((1 2) (3 4)) 1 2 3 4 1 3 4 2 1 3 4 2

List of Symbols (shorthand) ‘(a b c) translates into (‘a ‘b ‘c)

Yet More Examples (define p (cons 1 2)) p (1 . 2) 3 p1 p1 (3 1 . 2) 1 2 p p2 (define p2 (list p p)) p2 ( (1 . 2) (1 . 2) )

The Predicate Null? (null? <z>) null? : anytype -> boolean #t if <z> evaluates to empty list #f otherwise (null? 2)  #f (null? (list 1))  #f (null? (cdr (list 1)))  #t (null? ’())  #t (null? null)  #t The beauty of list is that cdr allows us to easily move down a list, and we have a simple test to find out when we have reached the end, we get to the empty list, that is, to a list whose value is null. How do we check that we have reached the end, scheme supplies us with the predicate null?

The Predicate Pair? pair? : anytype -> boolean (pair? <z>) #t if <z> evaluates to a pair #f otherwise. (pair? (cons 1 2))  #t (pair? (cons 1 (cons 1 2)))  #t (pair? (list 1))  #t (pair? ’())  #f (pair? 3)  #f (pair? pair?)  #f

The Predicate Atom? atom? : anytype -> boolean (define (atom? z) (and (not (pair? z)) (not (null? z)))) (define (square x) (* x x)) (atom? square)  #t (atom? 3)  #t (atom? (cons 1 2))  #f Not a primitive procedure

More examples ? ? (define digits (list 1 2 3 4 5 6 7 8 9)) (define digits1 (cons 0 digits)) digits1 (define l (list 0 digits)) l ? ? (0 1 2 3 4 5 6 7 8 9) (0 (1 2 3 4 5 6 7 8 9))

The procedure length (define digits (list 1 2 3 4 5 6 7 8 9)) (length digits) 9 (define l null) (length l) (define l (cons 1 l)) (length l) 1 (define (length l) (if (null? l) 0 (+ 1 (length (cdr l)))))

The procedure append (define (append list1 list2) (cond ((null? list1) list2) ; base (else (cons (car list1) ; recursion (append (cdr list1) list2)))))

Constructor Type: Number * T -> LIST(T) > (make-list 7 ’foo) (foo foo foo foo foo foo foo) > (make-list 5 1) (1 1 1 1 1)

List type Pairs: For every type assignment TA and type expressions S,S1,S2: TA |- cons:[S1*S2 -> PAIR(S1,S2)] TA |- car:[PAIR(S1,S2) -> S1] TA |- cdr:[PAIR(S1,S2) -> S2] TA |- pair?:[S -> Boolean] TA |- equal?:[PAIR(S1,S2)*PAIR(S1,S2) -> Boolean]

For every type environment TEnv and type expression S: TEnv |- list:[Unit -> LIST(S)] TEnv |- cons:[T*LIST(S) -> LIST(S)] TEnv |- car:[LIST(S) -> S] TEnv |- cdr:[LIST(S) -> LIST(S)] TEnv |- null?:[LIST(S) -> Boolean] TEnv |- list?:[S -> Boolean] TEnv |- equal?:[LIST(S)*LIST(S) -> Boolean]

Cont. For every type environment TEnv and type expression S: TEnv |- list:[Unit -> LIST] TEnv |- cons:[S*LIST -> LIST] TEnv |- car:[LIST -> S] TEnv |- cdr:[LIST -> LIST] TEnv |- null?:[LIST -> Boolean] TEnv |- list?:[S -> Boolean] TEnv |- equal?:[LIST*LIST -> Boolean]

Procedural abstraction Publish: name, number and type of arguments (and conditions they must satisfy) type of procedure’s return value Guarantee: the behavior of the procedure Hide: local variables and procedures, way of implementation, internal details, etc. Interface Implementation Export only what is needed.

Data-object abstraction Publish: constructors, selectors Guarantee: the behavior Hide: local variables and procedures, way of implementation, internal details, etc. Interface Implementation Export only what is needed.

An example: Rational numbers We would like to represent rational numbers. A rational number is a quotient a/b of two integers. Constructor: (make-rat a b) Selectors: (numer r) (denom r) Guarantee: (numer (make-rat a b)) = a (denom (make-rat a b)) = b

An example: Rational numbers We would like to represent rational numbers. A rational number is a quotient a/b of two integers. Constructor: (make-rat a b) Selectors: (numer r) (denom r) A better Guarantee: (numer (make-rat a b)) a = (denom (make-rat a b)) b A weaker condition, but still sufficient!

We can now use the constructors and selectors to implement operations on rational numbers: (add-rat x y) (sub-rat x y) (mul-rat x y) (div-rat x y) (equal-rat? x y) (print-rat x) A form of wishful thinking: we don’t know how make-rat numer and denom are implemented, but we use them.

Implementing the operations (define (add-rat x y) ;n1/d1 + n2/d2 = (n1.d2 + n2.d1) / (d1.d2) (make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (sub-rat x y) … (define (mul-rat x y) (make-rat (* (numer x) (numer y)) (* (denom x) (denom y)))) (define (div-rat x y) (make-rat (* (numer x) (denom y)) (* (denom x) (numer y)))) (define (equal-rat? x y) (= (* (numer x) (denom y)) (* (numer y) (denom x))))

Using the rational package (define (print-rat x) (newline) (display (numer x)) (display ”/”) (display (denom x))) (define one-half (make-rat 1 2)) (print-rat one-half)  1/2 (define one-third (make-rat 1 3)) (print-rat (add-rat one-half one-third))  5/6 (print-rat (add-rat one-third one-third))  6/9

Abstraction barriers Programs that use rational numbers rational numbers in problem domain add-rat sub-rat mul-rat… rational numbers as numerators and denumerators make-rat numer denom

Gluing things together We still have to implement numer, denom, and make-rat We need a way to glue things together… A pair: (define x (cons 1 2)) (car x)  1 (cdr x)  2

Implementing make-rat, numer, denom (define (make-rat n d) (cons n d)) (define (numer x) (car x)) (define (denom x) (cdr x))

Abstraction barriers Programs that use rational numbers rational numbers in problem domain add-rat sub-rat mul-rat... rational numbers as numerators and denumerators make-rat numer denom rational numbers as pairs cons car cdr

Alternative implementation for add-rat Abstraction Violation (define (add-rat x y) (cons (+ (* (car x) (cdr y)) (* (car y) (cdr x))) (* (cdr x) (cdr y)))) If we bypass an abstraction barrier, changes to one level may affect many levels above it. Maintenance becomes more difficult.

Rationals - Alternative Implementation In our current implementation we keep 10000/20000 as such and not as 1/2. This: Makes the computation more expensive. Prints out clumsy results. A solution: change the constructor (define (make-rat a b) (let ((g (gcd a b))) (cons (/ a g) (/ b g)))) No other changes are required!

Reducing to lowest terms, another way (define (make-rat n d) (cons n d)) (define (numer x) (let ((g (gcd (car x) (cdr x)))) (/ (car x) g))) (define (denom x) (/ (cdr x) g)))

How can we implement pairs? (first solution – “lazy” implementation) (define (cons x y) (lambda (f) (f x y))) (define (car z) (z (lambda (x y) x))) (define (cdr z) (z (lambda (x y) y)))

How can we implement pairs? (first solution, cont’) Name Value (lambda(f) (f 1 2)) p > (define p (cons 1 2)) > (car p) ( (lambda(f) (f 1 2)) (lambda (x y) x)) ( (lambda(x y) x) 1 2 ) (define (cons x y) (lambda (f) (f x y))) > 1 (define (car z) (z (lambda (x y) x))) (define (cdr z) (z (lambda (x y) y)))

How can we implement pairs? (Second solution: “eager” implementation) (define (cons x y) (lambda (m) (cond ((= m 0) x) ((= m 1) y) (else (error "Argument not 0 or 1 -- CONS" m)))))) (define (car z) (z 0)) (define (cdr z) (z 1))

Implementing pairs (second solution, cont’) Name Value > (define p (cons 3 4)) p (lambda(m) (cond ((= m 0) 3) ((= m 1) 4) (else ..))) > (car p) ((lambda(m) (cond ..)) 0) (cond ((= 0 0) 3) ((= 0 1) 4) (else ...))) (define (cons x y) (lambda (m) (cond ((= m 0) x) ((= m 1) y) (else ...))) > 3 (define (car z) (z 0)) (define (cdr z) (z 1))