280 likes | 409 Views
Lecture #7. Constructor:. Selectors:. The rational number abstraction. Wishful thinking:. ( make-rat <n> <d>) Creates a rational number <r>. ( numer <r>) Returns the numerator of <r>. ( denom <r>) Returns the denominator of <r>.
E N D
Lecture #7 מבוא מורחב
Constructor: Selectors: The rational number abstraction Wishful thinking: (make-rat <n> <d>) Creates a rational number <r> (numer <r>) Returns the numerator of <r> (denom <r>) Returns the denominator of <r> מבוא מורחב
(numer (make-rat <n> <d>)) <n> = <d> (denom (make-rat <n> <d>)) A contract How do we do it ? מבוא מורחב
Using pairs (define (make-rat n d) (cons n d)) (define (numer x) (car x)) (define (denom x) (cdr x)) מבוא מורחב
Abstraction Violation Alternative implementation (define (add-rat x y) (make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (add-rat x y) (cons (+ (* (car x) (cdr y)) (* (car y) (cdr x))) (* (cdr x) (cdr y)))) מבוא מורחב
Reducing to lowest terms (define (make-rat n d) (let ((g (gcd n d))) (cons (/ n g) (/ d g)))) מבוא מורחב
Abstraction barriers Programs that use rational numbers add-rat sub-rat ……. make-rat numer denom car cdr cons מבוא מורחב
How can we implement pairs ? (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)) מבוא מורחב
The pair constructed by (cons 6 9) is the procedure (lambda (m) (cond ((= m 0) 6) ((= m 1) 9) (else (error “Argument not 0 or 1 -- CONS” m)))) מבוא מורחב
In the book: (define (cons x y) (define (dispatch m) (cond ((= m 0) x) ((= m 1) y) (else (error "Argument not 0 or 1 -- CONS" m)))) dispatch) (define (car z) (z 0)) (define (cdr z) (z 1)) מבוא מורחב
Compound data • Ideally want the result of this “gluing” to have the property of closure: • “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” מבוא מורחב
3 2 1 Box and pointer diagram • Note how pairs have the property of closure – we can use the result of a pair as an element of a new pair: • (cons (cons 1 2) 3) מבוא מורחב
4 3 1 2 Box and pointer diagram • (cons (cons 1 (cons 2 3)) 4) מבוא מורחב
3 Lists • (cons 1 (cons 3 (cons 2 ‘()))) 1 2 מבוא מורחב
lists • A list is either • ‘() (The empty list) • A pair whose cdr is a list. • Note that lists are closed under operations of cons and cdr. מבוא מורחב
… <el1> <el2> <eln> Lists • (list <el1> <el2> ... <eln>) • Same as (cons <el1> (cons <el2> (cons … (cons <eln> ‘())))) מבוא מורחב
Lists • Predicates ; null? anytype -> boolean(null? <z>) ==> #t if <z> evaluates to empty list ; pair? anytype -> boolean(pair? <z>) ==> #t if <z> evaluates to a pair ; atom? anytype -> boolean(define (atom? z) (and (not (pair? z)) (not (null? z)))) מבוא מורחב
Lists -- examples (define one-to-four (list 1 2 3 4)) one-to-four ==> (1 2 3 4) (1 2 3 4) ==> error (car one-to-four) ==> 1 2 (car (cdr one-to-four)) ==> (cadr one-to-four) ==> 2 3 (caddr one-to-four) ==> מבוא מורחב
2 3 3 4 4 4 Common Pattern #1: cons’ing up a list (define (enumerate-interval from to) (if (> from to) nil (cons from (enumerate-interval (+ 1 from) to)))) (e-i 2 4) (if (> 2 4) nil (cons 2 (e-i (+ 1 2) 4))) (if #f nil (cons 2 (e-i 3 4))) (cons 2 (e-i 3 4)) (cons 2 (cons 3 (e-i 4 4))) (cons 2 (cons 3 (cons 4 (e-i 5 4)))) (cons 2 (cons 3 (cons 4 nil))) (cons 2 (cons 3 )) (cons 2 ) ==> (2 3 4) מבוא מורחב
Common Pattern #2: cdr’ing down a list (define (list-ref lst n) (if (= n 0) (car lst) (list-ref (cdr lst) (- n 1)))) (define squares (list 1 4 9 16 25)) (list-ref squares 3) ==> 16 מבוא מורחב
Common Pattern #2: cdr’ing down a list (define (length lst) (if (null? lst) 0 (+ 1 (length (cdr lst))))) (define odds (list 1 3 5 7)) (length odds) ==> 4 מבוא מורחב
Iterative length (define (length items) (define (length-iter a count) (if (null? a) count (length-iter (cdr a) (+ 1 count)))) (length-iter items 0)) מבוא מורחב
Cdr’ing and Cons’ing Examples (define (append list1 list2) (cond ((null? list1) list2) ; base (else (cons (car list1) ; recursion (append (cdr list1) list2))))) (append (list 1 2) (list 3 4)) (cons 1 (append (2) (3 4))) (cons 1 (cons 2 (append () (3 4)))) (cons 1 (cons 2 (3 4))) ==> (1 2 3 4) T(n) = (n)
Reverse (reverse (list 1 2 3 4)) ==> (4 3 2 1) (define (reverse lst) (cond ((null? lst) lst) (else (append (reverse (cdr lst)) (list (car lst))))))) (reverse (list 1 2 3)) (append (reverse (2 3)) (1)) (append (append (reverse (3)) (2)) (1)) (append (append (append (reverse ()) (3)) (2)) (1)) Append: T(n) = c*n (n) Reverse: T(n) = c*(n-1) + c*(n-2) … c*1 (n2)
Shall we have some real fun .. Lets write a procedure scramble.. (scramble (list 0 1 0 2)) ==> (0 0 0 1) (scramble (list 0 0 0 2 3 1 0 0 8 1)) ==> (0 0 0 0 0 3 0 0 0 8) (scramble (list 0 1 2 3 4 5 6 7)) ==> (0 0 0 0 0 0 0 0) (scramble (list 0 1 2 1 2 1 2 1 2)) ==> ( 0 0 0 2 2 2 2 2 2) מבוא מורחב
Ok ok Each number in the argument is treated as backword index from its own position to a point earlier in the tup. The result at each position is found by counting backward from the current position according to this index ==> No number can be greater than its index מבוא מורחב
tup = (0 1 2 1) rev-pre = () (cons 0 …. tup = (1 2 1) rev-pre = (0) (cons 0 (cons 0 tup = (2 1) rev-pre = (1 0) (cons 0 (cons 0 (cons 0 tup = (1) rev-pre = (2 1 0) (cons 0 (cons 0 (cons 0 (cons 2 tup = ( ) rev-pre = (1 2 1 0) (cons 0 (cons 0 (cons 0 (cons 2 ())))) מבוא מורחב
(define (scramble-i tup rev-pre) (if (null? tup) '() (cons ( (cons (car tup) rev-pre) (car tup)) ( (cdr tup) (cons (car tup) rev-pre))))) list-ref scramble-i (define (scramble tup) (scramble-b tup '())) מבוא מורחב