TDDC74 Programming: Abstraktion och modellering VT 2014 Johannes Schmidt Institutionen för datavetenskap Linköpings universitet Lecture 6 Data Abstraction * * * * * Manual debugging, find hidden syntax errors Data Abstraktion: Family example Data Abstraktion: Binary Tree example PUTPROP, GETPROP, APPLY Data Abstraktion: Data-Directed-Prog. example * SICP 2, Del 3 Manual debugging What is debugging? Find and fix a bug. What is a bug? A semantic error. (compilable / evaluabe but it does not behave as desired) Manual debugging Example: (define pi 4.141592) (define (get-circle-area r) (* r r r pi)) (define my-circle-radius 5) ; radius is 6, => expected area: 113.097 > (get-circle-area my-circle-radius) 517.699 What to do: Enrich your code (temporarily) with additional instructions, such as checks (conditions) and display instructions, such that it might display helpful information, in order to localize the bug. Find hidden syntax errors Sometimes an expression (or a whole program) does not compile (is not evaluable) but the compilers/interpreters indications are not helpful to localize the faulty piece of code. What to do? Binary search with outcommenting (big) pieces of code! #| … |# Data Abstraction: What properties does a person have? A person has: - Name - Birth year - Father - Mother - Sex - … Data Abstraktion: Using a person object ; Constructor (create-person name birthyear father mother sex) ; Selectors (name person) (birthyear person) (father person) (mother person) (sex person) ; Recognizers (define (female? person) (eq? (sex person) 'w)) (define (male? person) (eq? (sex person) 'm)) ; Comparators (define (older p1 p2)(< (birthyear p1) (birthyear p2))) Implementation of Constructor and Selectors (v1) ; Constructor (define (create-person nameP birthyearP fatherP motherP sexP) (list nameP birthyearP fatherP motherP sexP)) ; Selectors (define (name person) (car person)) (define (birthyear person) (cadr person)) (define (father person) (caddr person)) (define (mother person) (cadddr person)) (define (sex person) (cadddr (cdr person))) Implementation of Constructor and Selectors (v2) ; Constructor (define (create-person nameP birthyearP fatherP motherP sexP) (list birthyearP nameP fatherP motherP sexP)) ; Selectors (define (birthyear person) (car person)) (define (name person) (cadr person)) (define (father person) (caddr person)) (define (mother person) (cadddr person)) (define (sex person) (cadddr (cdr person))) assv (assv e lst) – lst must be a list of pairs. Locates the first element of lst whose car is equal to e according to eqv?. If such an element exists, the pair (i.e., an element of lst) is returned. Otherwise, the result is #f. (define mylist (list (cons (cons (cons (cons (assv 'key3 mylist ) > (key3 . 11) 'key1 'key2 'key3 'key4 3) 17) 11) 242))) Implementation of Constructor and Selectors (v3) ; Constructor (define (create-person nameP birthyearP fatherP motherP sexP) (list (cons 'name nameP) (cons 'birthyear birthyearP) (cons 'father fatherP) (cons 'mother motherP) (cons 'sex sexP))) ; Selectors (define (name person) (cdr (assv 'name person))) (define (birthyear person) (cdr (assv 'birthyear person))) (define (father person) (cdr (assv 'father person))) (define (mother person) (cdr (assv 'mother person))) (define (sex person) (cdr (assv 'sex person))) Binary trees in programming root 3 parent children 8 2 9 6 4 leaves 7 Each node has: 1. Value 2. left child 3. right child What properties do we need from a (binary) tree? A node-entity, with methods: get-value – returns the nodes value get-left – returns the left branch get-right – returns the right branch leaf? – test if the tree is a leaf (no children) empty? – test if the tree is empty Constructor – (make-btree value left right) Implementation of Constructor and Selectors (v1) ; Constructors (define (make-btree value left right) (list value left right)) (define (make-empty-btree) '()) ; Selectors (define (get-value btree) (car btree)) (define (get-left btree) (car (cdr btree))) (define (get-right btree) (car (cdr (cdr btree)))) ; Predicates (define (empty-btree? btree) (eqv? btree (make-empty-btree))) (define (leaf? btree) (and (empty-btree? (get-left btree)) (empty-btree? (get-right btree)))) Implementation of Constructor and Selectors (v2) ; Constructors (define (make-btree value left right) (cons value (cons left right))) (define (make-empty-btree) 'E) ; Selectors (define (get-value btree) (car btree)) (define (get-left btree) (car (cdr btree))) (define (get-right btree) (cdr (cdr btree))) ; Predicates : unchanged! (define (empty-btree? btree) (eqv? btree (make-empty-btree))) (define (leaf? btree) (and (empty-btree? (get-left btree)) (empty-btree? (get-right btree)))) Is e present in the tree? Exhaustive search: (define (btree-present? e btree) (cond ((empty-btree? btree) #f) ((equal? (get-value btree) e) #t) (else (or (btree-present? e (get-left btree)) (btree-present? e (get-right btree)))))) A remark on binary search Intelligent search: (only possible if the tree is a Binary Search Tree: left branch = smaller elements, right branch = greater elements) (define (bstree-present? e btree) (cond ((empty-btree? btree) #f) ((equal? (get-value btree) e) #t) (else (if (< e (get-value btree)) (bstree-present? e (get-left btree)) (bstree-present? e (get-right btree)))))) Scenario: represent geometric objects v1 (define (make-circle radius) radius) (define (make-square side) side) (define (make-rect a b) (cons a b)) (define (circle-area radius) (* radius radius pi)) (define (square-area side) (* side side)) (define (rect-area param) (* (car param) (cdr param))) (define (circle-circ radius) (* 2 radius pi)) (define (square-circ side) (* side 4)) (define (rect-circ param) (+ (* 2 (car param)) (* 2 (cdr param)))) Scenario: represent geometric objects v2 (define (make-circle radius) (list 'circle radius)) (define (make-square side) (list 'square side)) (define (make-rect a b) (list 'rect a b)) (define (circle-area param) (* (car param) (car param) pi)) (define (square-area param) (* (car param) (car param))) (define (rect-area param) (* (car param) (cadr param))) (define (circle-circ param) (* 2 (car param) pi)) (define (square-circ param) (* (car param) 4)) (define (rect-circ param) (+ (* 2 (car param)) (* 2 (cadr param)))) (define (tag object) (car object)) (define (data object) (cdr object)) Scenario: represent geometric objects v2 (define (area object) (cond ((eqv? (tag object) 'circle) (circle-area (data object))) ((eqv? (tag object) 'square) (square-area (data object))) ((eqv? (tag object) 'rect) (rect-area (data object))))) (define (circ object) (cond ((eqv? (tag object) 'circle) (circle-circ (data object))) ((eqv? (tag object) 'square) (square-circ (data object))) ((eqv? (tag object) 'rect) (area mycircle) (area mysquare) (rect-circ (data object))))) Uniform area and circ methods for all objects! (circ mysquare) But we can make that more elegant… (circ myrect) 1. Use apply 2. use putprop / getprop Apply (apply proc l) – applies proc to the parameters in the list l. > (apply + '(1 2 3)) 6 > (apply inc '(6)) 7 > (apply cons '(4 a)) '(4 . a) putprop / getprop (putprop object-type operation-name object-type-specific-operation) Saves the 3-tuple in a table. (getprop object-type operation-name) Allows to retrieve the accociated object-type-specific-operation. Scenario: represent geometric objects v3 (define (make-circle radius) (list 'circle radius)) (define (make-square side) (list 'square side)) (define (make-rect a b) (list 'rect a b)) (define (circle-area radius) (* radius radius pi)) (define (square-area side) (* side side)) (define (rect-area a b) (* a b)) (define (circle-circ radius) (* 2 radius pi)) (define (square-circ side) (* side 4)) (define (rect-circ a b) (+ (* 2 a) (* 2 b))) (define (tag object) (car object)) (define (data object) (cdr object)) Scenario: represent geometric objects v3 (putprop 'circle 'area circle-area) (putprop 'square 'area square-area) (putprop 'rect rect-area) 'area (define (area object) (let* ((tag (tag object)) (proc (getprop tag 'area))) (if (not proc) (error "No area method found -- AREA" tag) (apply proc (data object))))) (area mycircle) (area mysquare) (area myrect) SICP on Data Abstraction The basic idea of data abstraction is to structure the programs that are to use compound data objects so that they operate on “abstract data.” That is, our programs should use data in such a way as to make no assumptions about the data that are not strictly necessary for performing the task at hand. At the same time, a “concrete” data representation is defined independent of the programs that use the data. The interface between these two parts of our system will be a set of procedures, called selectors and constructors, that implement the abstract data in terms of the concrete representation. – Abelson, Sussman, & Sussman: SICP SICP on Data Abstraction The basic idea of data abstraction is to structure the programs that are to use compound data objects so that they operate on “abstract data.” That is, our programs should use data in such a way as to make no assumptions about the data that are not strictly necessary for performing the task at hand. At the same time, a “concrete” data representation is defined independent of the programs that use the data. The interface between these two parts of our system will be a set of procedures, called selectors and constructors, that implement the abstract data in terms of the concrete representation. – Abelson, Sussman, & Sussman: SICP Data Abstraction - essence Specify an interface. Make its Implementation Independent from its Usage. Data Abstraktion: Using a person object Interface Specification No scheme code! ; Constructor (create-person name birthyear father mother sex) ; Selectors (name person) (birthyear person) (father person) (mother person) (sex person) ; Recognizers (define (female? person) (eq? (sex person) 'w)) (define (male? person) (eq? (sex person) 'm)) ; Comparators (define (older p1 p2)(< (birthyear p1) (birthyear p2))) Data Abstraktion: Using a person object Usage ; Constructor (create-person name birthyear father mother sex) ; Selectors (name person) (birthyear person) (father person) (mother person) (sex person) ; Recognizers (define (female? person) (eq? (sex person) 'w)) (define (male? person) (eq? (sex person) 'm)) ; Comparators (define (older p1 p2)(< (birthyear p1) (birthyear p2))) Implementation of Constructor and Selectors (v1) ; Constructor (define (create-person nameP birthyearP fatherP motherP sexP) (list nameP birthyearP fatherP motherP sexP)) ; Selectors (define (name person) (car person)) (define (birthyear person) (cadr person)) (define (father person) (caddr person)) (define (mother person) (cadddr person)) (define (sex person) (cadddr (cdr person))) Implementation What properties do we need from a (binary) tree? A node-entity, with methods: Interface Specification get-value – returns the nodes value get-left – returns the left branch get-right – returns the right branch leaf? – test if the tree is a leaf (no children) empty? – test if the tree is empty Constructor – (make-btree value left right) Is e present in the tree? Usage Exhaustive search: (define (btree-present? e btree) (cond ((empty-btree? btree) #f) ((equal? (get-value btree) e) #t) (else (or (btree-present? e (get-left btree)) (btree-present? e (get-right btree)))))) Implementation of Constructor Implementation and Selectors (v1) ; Constructors (define (make-btree value left right) (list value left right)) (define (make-empty-btree) '()) ; Selectors (define (get-value btree) (car btree)) (define (get-left btree) (car (cdr btree))) (define (get-right btree) (car (cdr (cdr btree)))) ; Predicates (define (empty-btree? btree) (eqv? btree (make-empty-btree))) (define (leaf? btree) (and (empty-btree? (get-left btree)) (empty-btree? (get-right btree))))