Download - Introduction to Computer Science I Topic 3: Recursive Data Types and Structural Recursion
Telecooperation/RBG
Technische Universität Darmstadt
Copyrighted material; for TUD student use only
Introduction to Computer Science ITopic 3: Recursive Data Types and
Structural RecursionProf. Dr. Max MühlhäuserDr. Guido Rößling
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists• Structures are useful for storing data objects that contain a
fixed number of elements • However, in many cases we do not know how many
elements a data structure consists of– or the structure of the data is recursive
• Using recursive data types, we can store data objects of arbitrary size in a structured way
• Idea: One element of the data structure stores (directly or indirectly) another instance of the data structure– This is what we call a recursive data structure– A recursion anchor is needed for a finite data structure– To build this recursion anchor, we use the method for
heterogeneous data from our last lecture
2
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Building Recursive Data Types
• A list lst is either– the empty list, the-emptylst, or– (make-lst s r), where s is a value and r is a list
3
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists• Building lists with structures
4
(define-struct lst (first rest))(define-struct emptylst ())(define the-emptylst (make-emptylst))
;; a list with 0 elements(define list0 the-emptylst)
;; a list with 1 element(define list1 (make-lst 'a the-emptylst))
;; a list with 2 elements(define list2 (make-lst 'a (make-lst 'b the-emptylst)))
;; get the 2nd element from list2(lst-first (lst-rest list2)) 'b
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists• Lists are an important data type and therefore
there is a built-in data type for them– (also because of historical reasons)– Constructor with 2 arguments: cons (for construct)
• equivalent to make-lst from previous slide– The empty list: empty
• equivalent to the-emptylst – Selectors: first for the first element, rest for the
second element• equivalent to lst-first, lst-rest• “historical” names for first and rest: car and cdr
– Predicates: list?, empty?• equivalent to lst?, emptylst?
5
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists
• Example
6
;; a list with 0 elements;; (define list0 the-emptylst)(define list0 empty)
;; a list with 1 element;; (define list1 (make-lst 'a the-emptylst))(define list1 (cons 'a empty))
;; a list with 2 elements;; (define list2 (make-lst 'a ;; (make-lst 'b the-emptylst)))(define list2 (cons 'a (cons 'b empty)))
;; get the 2nd element from list2;; (lst-first (lst-rest list2)) 'b(first (rest list2)) 'b
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists• The only difference between make-lst and cons:
– cons expects empty or (cons … ) as second argument– E.g. (cons 1 2) throws an error, (make-lst 1 2) doesn’t– Thus, cons prevents incorrect use
• however, this check is missing in other versions of Scheme• A better emulation would look like this:
• But this can not avoid that the user uses make-lst directly 7
(define-struct lst (first rest))(define-struct emptylst ())(define the-emptylst (make-emptylst))
(define (our-cons a-value a-list) (cond [(emptylst? a-list) (make-lst a-value a-list)] [(lst? a-list) (make-lst a-value a-list)] [else (error 'our-cons "list as second argument expected")]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists
8
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Lists• In general, a list does not have to contain values
of one kind, but may contain arbitrary values
9
(cons 0 (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 (cons 7 (cons 8 (cons 9 empty))))))))))
(cons 'RobbyRound (cons 3 (cons true empty)))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Closure Property• An operation for combining data objects
satisfies the closure property if the results of combining things with that operation can themselves be combined using the same operation– Example: cons
• Such combination operators permit us to create hierarchical data structures.
10
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Closure Property
11
Question: Have we seen the closure property before?
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Closure Property• Origin of the word „closure“
– Abstract algebra: A set of elements is said to be closed under an operation, if applying the operation to elements in the set produces an element that is again an element of the set
12
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Closure Property• The thought that an instrument of combination
satisfies the closure property is very intuitive
• Unfortunately, the combination operators of many languages do not satisfy closure– We can combine elements by storing them in an array– However, in some languages one cannot build arrays of
arrays or not use them as parameter/return types– Lack of a built-in general-purpose “glue” that makes it
easy to manipulate compound data in a uniform way
13
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The list Constructor• Creating longer lists with cons is somewhat
tedious
• Therefore there is a constructor called list– accepts any number of arguments– creates a list with all arguments as elements– e.g. (list 1 2 3) instead of
(cons 1 (cons 2 (cons 3 empty)))– e.g. (list (list ‘a 1) (list ‘b 2))
• In general (list exp-1 … exp-n) is equivalent to (cons exp-1 (cons … (cons exp-n empty ) … ))
14
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The ‘ / quote Constructor• Lists and symbols can be abbreviated even more
by using the quote constructor '– '(1 2 3) is short for (list 1 2 3)– '((1 2) (3 4) (5 6)) stands for(list (list 1 2) (list 3 4) (list 5 6))
– '(a b c) stands for (list 'a 'b 'c)• Don’t confuse this with (list a b c) – list evaluates all
arguments, quote does not– In general, '(exp-1 … exp-n) is equivalent to(list 'exp-1 … 'exp-n), where 'exp-i = exp-i for all self-evaluating values (numbers, booleans)
• Note that this rule is recursive!• To use list and quote,
– please use the level “Beginning Student with List Abbreviations” in DrScheme from now on!
15
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Handling recursive data types• How do we handle instances of recursive data
types?– Answer: We use our design method for heterogeneous
data– Example: Does a special symbol occur in a list of
symbols?• 1st Step: Definition of the contract, Header etc.
– Note the convention list-of-XXX to document in the contract what kind of data is expected as list elements
16
;; contains-doll? : list-of-symbols -> boolean;; to determine whether the symbol 'doll occurs ;; on a-list-of-symbols(define (contains-doll? a-list-of-symbols) ...)
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Handling recursive data types• Creating templates
– Write a cond-branch for each data type; indicate selectors
• First Case (empty list) is trivial
17
(define (contains-doll? a-list-of-symbols) (cond [(empty? a-list-of-symbols) ...] [(cons? a-list-of-symbols) ... (first a-list-of-symbols) ... ... (rest a-list-of-symbols) ...]))
(define (contains-doll? a-list-of-symbols) (cond [(empty? a-list-of-symbols) false] [(cons? a-list-of-symbols) ... (first a-list-of-symbols) ... ... (rest a-list-of-symbols) ...]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Handling recursive data types• We can already test the first element of the list
with the available data
• What do we do with the rest of the list?– We need an auxiliary procedure, which tests if the (rest of
the) list contains the symbol– This auxiliary procedure is contains-doll? itself! 18
(define (contains-doll? a-list-of-symbols) (cond [(empty? a-list-of-symbols) false] [(cons? a-list-of-symbols) (cond [(symbol=? (first a-list-of-symbols) 'doll) true] ... (rest a-list-of-symbols) ...]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Handling recursive data types• Solution:
19
(define (contains-doll? a-list-of-symbols) (cond [(empty? a-list-of-symbols) false] [(cons? a-list-of-symbols) (cond [(symbol=? (first a-list-of-symbols) 'doll) true] [else (contains-doll? (rest a-list-of-symbols))]) ]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Handling recursive data types• Why is it this solution well-defined?
– Here, well-defined means that the evaluation of the procedure terminates
• Not every recursive definition leads to a well-defined function!– e.g. (define (f a-bool) (f (not a-bool)))
• Our recursive definition is an example of structural recursion– The structure of the procedure follows the (recursive) structure
of the data– Such recursive definitions are always well defined, because the
nesting depth of the data is reduced after each recursive call
20
(define (contains-doll? a-list-of-symbols) (cond [(empty? a-list-of-symbols) false] [(cons? a-list-of-symbols) (cond [(symbol=? (first a-list-of-symbols) 'doll) true] [else (contains-doll? (rest a-list-of-symbols))]) ]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of procedures for recursive data• How does our design concept change?
– Data analysis and design• If the problem description involves information of arbitrary
size, we need a recursive data structure• The definition of this data structure needs at least two
cases, at least one of which must not (directly or indirectly) refer back to the definition
– Contract and procedure header: no changes– Examples: no changes– Template: Indicate the recursive call in the recursive branches– Procedure body
• First, implement the basic (non-recursive) branches, then the recursive branches. For the recursive calls, assume that the procedure already works as desired
– Test: no changes
21
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Creating recursive data• Procedures that process recursive data according
to our design method usually combine the result of recursive call(s) with the non-recursive data
• This combination often consists of the construction of new data which has the same structure as the input
22
(define (sum a-list-of-nums) (cond [(empty? a-list-of-nums) 0] [else (+ (first a-list-of-nums) (sum (rest a-list-of-nums)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Creating recursive data• Computation of the wage
– of a person or multiple people
23
;; wage : number -> number;; to compute the total wage (at $12 per hour);; of someone who worked for h hours(define (wage h) (* 12 h))
;; hours->wages : list-of-numbers -> list-of-numbers;; to create a list of weekly wages from ;; a list of weekly hours (alon)(define (hours->wages alon) (cond [(empty? alon) empty] [else (cons (wage (first alon)) (hours->wages (rest alon)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Structures that contain Structures• Structures (and lists) do not necessarily have to contain atomic
data– They can e.g. contain instances of their own structure as elements
(as in the list structure)– They may also contain any other types of structures/lists
• e.g. list of points, list of lists of points
• Example:– A inventory record is a structure (make-ir s n), s being a
symbol and n a (positive) number:(define-struct ir (name price))
– An inventory-list is either1. empty, or2. (cons ir inv), ir being an inventory record and inv an
inventory-list
24
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Structure of Natural Numbers• Often, natural numbers are described by means of an
enumeration: 0,1,2, etc.– However, we cannot program “etc.”
• Using a recursive definition, we can get rid of “etc.”:– 0 is a natural number – If n is a natural number, then so is the successor of n (succ n)– This definition generates: 0, (succ 0), (succ (succ 0)) etc.– Cf. the Peano-Axioms from mathematics
• This is analogous to the construction of lists– cons is equivalent to succ– rest is equivalent to pred– empty? is equivalent to zero?
• Therefore, functions that operate on natural numbers and functions that operate on lists can be structured in the same way!
25
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Structure of Natural Numbers• Here is the definition of the new procedures pred and succ:
26
;; pred: N -> N;; returns the predecessor of n; if n is 0, return 0(define (pred n) (if (> n 0) (- n 1) 0 ))
;; succ: N -> N;; returns the successor of n; if negative, return 0(define (succ n) (if (> n -1) (+ n 1) 0 ))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
The Structure of Natural Numbers• Example 1
• Example 2
27
;; hellos : N -> list-of-symbols;; to create a list of n copies of 'hello(define (hellos n) (cond [(zero? n) empty] [else (cons 'hello (hellos (pred n)))]))
;; ! : N -> N;; computes the faculty function(define (! n) (cond [(zero? n) 1] [else (* n (! (pred n)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Intermezzo
Design of auxiliary procedures revisited
28
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: wish lists
• Larger programs are made up of many different (auxiliary) procedures
• Suggested method: Creation and maintenance of a wish list of auxiliary procedures– A list of procedures that are missing to complete a
program• The procedures of the wish list can be
implemented stepwise by means of our design method
• The wish list will often change during implementation– e.g. one discovers that new auxiliary procedures are
needed29
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: wish lists
The order of processing the wish list is important– “Bottom-Up”-approach: First implement the procedures
that do not depend on any other procedure of the wish list
• Advantage: We can test immediately and at any time• Disadvantage: At the beginning it is often difficult to see
which procedures are needed on the lowest level; one might lose track of the “big picture”
– “Top-Down”- approach: First implement the main procedure, then those called by the main procedure, and so on
• Advantage : Incremental refinement of the program structure
• Disadvantage : Testing can only be done late; sometimes you discover way “down” that there is a conceptual error “higher up”
– Often a mix of Top-Down and Bottom-Up makes sense30
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: wish lists
• Example: Sorting a list of numbers– First, we follow our design method…
31
;; sort : list-of-numbers -> list-of-numbers ;; to create a sorted list of numbers from all;; the numbers in alon
;; Examples:;; (sort empty) empty;; (sort (cons 1297.04 (cons 20000.00 (cons -505.25 empty))));; (cons -505.25 (cons 1297.04 (cons 20000.00 empty)))
(define (sort alon) (cond [(empty? alon) ...] [else ... (first alon) ... (sort (rest alon)) ...]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: wish lists
• First case (empty list) is trivial• The call (sort (rest alon)) returns a sorted list in the
recursive case• (first alon) has to be sorted into this list • The procedure for doing this is added to our wish list; for
now we can complete the sort-procedure
32
;; insert : number list-of-numbers -> list-of-numbers;; to create a list of numbers from n and the numbers ;; in alon that is sorted in descending order; alon is ;; already sorted(define (insert n alon) ...)
(define (sort alon) (cond [(empty? alon) empty] [else (insert (first alon) (sort (rest alon)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: wish lists
• The insert-procedure can now be implemented independently of sort– important: detailed analysis of the different cases
– This type of sorting is known as Insertion-Sort
33
;; insert : number list-of-numbers (sorted) ;; -> list-of-numbers (sorted);; to create a list of numbers from n and the numbers on;; alon that is sorted in descending order; alon is sorted
(define (insert n alon) (cond [(empty? alon) (cons n empty)] [else (cond [(<= n (first alon)) (cons n alon)] [(> n (first alon)) (cons (first alon) (insert n (rest alon)))])]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: Generalization of Problems
• A more general problem is often easier to solve than the actual problem
• Approach: The auxiliary procedure solves the generalized problem, the main procedure specializes the auxiliary procedure to solve the actual problem
• Example: Changing coins– In how may different ways can we make change of 1 €,
given coins of 1, 2, 5, 10, 20 and 50 Cent?– Generalization: In how may different ways can we change
amount a using the first n types of coins from 1, 2, 5, 10, 20 and 50 Cent?
– Specialization: n = 6
34
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: Generalization of Problems
• Counting ways to change: Straightforward formulation of the generalized problem as recursive procedure:
– The number of ways to change amount a using n kinds of coins equals:
• 1 if a = 0• 0 if a<0 or n = 0• otherwise:
– the number of ways to change amount a using all but the last kind of coin, plus
– the number of ways to change amount a-d using all n kinds of coins, where d is the denomination of the last kind of coin.
35
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: Generalization of Problems
36
(define (count-change amount) (cc amount 6))
(define (cc amount kinds-of-coins) (cond [(= amount 0) 1] [(or (< amount 0) (= kinds-of-coins 0)) 0] [else (+ (cc amount (- kinds-of-coins 1)) (cc (- amount (denomination kinds-of-coins)) kinds-of-coins))]))
(define (denomination coin-number) (cond ((= coin-number 1) 1) ((= coin-number 2) 2) ((= coin-number 3) 5) ((= coin-number 4) 10) ((= coin-number 5) 20) ((= coin-number 6) 50)))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Design of auxiliary procedures: Generalization of Problems
• Comments on the count-change procedure:– This kind of recursion is different from structural
recursion, which you have seen before• More on this later
– This procedure needs a lot of computing• A lot of time may be needed for amounts >100• The time required increases exponentially with the size of
the amount • More on this later
37
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees
38
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees• Trees are one of the most important data
structures in computer science– representation of hierarchical relations
• Example: family trees
39
Carl (1926)Eyes: green
Bettina (1926)Eyes: green
Adam (1960)Eyes: yellow
Dave (1955)Eyes: black
Eva (1965)Eyes: blue
Fred (1966)Eyes: pink
Gustav (1988)Eyes: brown
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees• Data modeling, 1st attempt:
• Problem: It is impossible to create an instance of this data structure– The basic case is missing (termination of the recursion)– We failed to apply our rule for designing recursive data
structures• The definition of a recursive data structure needs at least
two cases, at least one of which must not be recursive
40
A child is a structure(make-child father mother name date eyes),where father and mother are child-structures; name and eyes are symbols, date is a number
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees• Data modeling, 2nd attempt :
• This definition conforms to our design rule; it can represent a family tree
41
A family tree node (ftn) is either
1. empty, or2.(make-child father mother name year eyes)
where father and mother are ftn; name and eyes are symbols, year is a number
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees• Carl: (make-child empty empty ‘Carl 1926 ‘green)• Adam:
(make-child (make-child empty empty ‘Carl 1926 ‘green) (make-child empty empty ‘Bettina 1926 ‘green) ‘Adam 1950 yellow)
42
redundancy!
Carl (1926)Eyes: green
Bettina (1926)Eyes: green
Adam (1960)Eyes: yellow
Dave (1955)Eyes: black
Eva (1965)Eyes: blue
Fred (1966)Eyes: pink
Gustav (1988)Eyes: brown
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees• Avoid redundancy by binding to names
43
;; Oldest Generation:(define Carl (make-child empty empty 'Carl 1926 'green))(define Bettina (make-child empty empty 'Bettina 1926 'green))
;; Middle Generation:(define Adam (make-child Carl Bettina 'Adam 1950 'yellow))(define Dave (make-child Carl Bettina 'Dave 1955 'black))(define Eva (make-child Carl Bettina 'Eva 1965 'blue))(define Fred (make-child empty empty 'Fred 1966 'pink))
;; Youngest Generation: (define Gustav (make-child Fred Eva 'Gustav 1988 'brown))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees• Design of functions on trees
– The method is the same, but it leads to more than one recursive call
• General template
44
;; fun-for-ftn : ftn -> ???(define (fun-for-ftn a-ftree) (cond [(empty? a-ftree) ...] [else ... (fun-for-ftn (child-father a-ftree)) ... ... (fun-for-ftn (child-mother a-ftree)) ... ... (child-name a-ftree) ... ... (child-date a-ftree) ... ... (child-eyes a-ftree) ...]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Trees
• Example: blue-eyed-ancestor?
45
;; blue-eyed-ancestor? : ftn -> boolean;; to determine whether a-ftree contains a child;; structure with 'blue in the eyes field
(define (blue-eyed-ancestor? a-ftree) (cond [(empty? a-ftree) false] [else (or (symbol=? (child-eyes a-ftree) 'blue) (or (blue-eyed-ancestor? (child-father a-ftree)) (blue-eyed-ancestor? (child-mother a-ftree))))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• Inverted example: Children instead of ancestors
46
Important difference for modeling: A person canhave any number of children, but only two ancestors (parents) We need a list to store the children
Carl (1926)Eyes: green
Bettina (1926)Eyes: green
Adam (1960)Eyes: yellow
Dave (1955)Eyes: black
Eva (1965)Eyes: blue
Fred (1966)Eyes: pink
Gustav (1988)Eyes: brown
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures
47
• We need two separate data structures:– A parent is a structure (make-parent children name
date eyes), where children is a list of children, name and eyes symbols, and date is a number.
– A list of children is either1. empty, or2. (cons p children), whereas p is a parent and children
is a list of children • Each of these definitions is useless when looked
at separately, because it refers to another data structure which has not yet been defined– Such data structures are called mutually recursive– Mutually recursive data structures should always be
defined together
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• Representation of the family tree
48
;; Youngest Generation:(define Gustav (make-parent empty 'Gustav 1988 'brown))
(define Fred&Eva (list Gustav))
;; Middle Generation:(define Adam (make-parent empty 'Adam 1950 'yellow))(define Dave (make-parent empty 'Dave 1955 'black))(define Eva (make-parent Fred&Eva 'Eva 1965 'blue))(define Fred (make-parent Fred&Eva 'Fred 1966 'pink))
(define Carl&Bettina (list Adam Dave Eva))
;; Oldest Generation:(define Carl (make-parent Carl&Bettina 'Carl 1926 'green))(define Bettina (make-parent Carl&Bettina 'Bettina 1926 'green))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• How do we create the procedure blue-eyed-descendant?
• Contract, description, header, examples:
49
;; blue-eyed-descendant? : parent -> boolean;; to determine whether a-parent or any of its descendants ;; (children, grandchildren, and so on) have 'blue ;; in the eyes field(define (blue-eyed-descendant? a-parent) ...)
;; Here are three simple examples, formulated as tests:
(boolean=? (blue-eyed-descendant? Gustav) false)(boolean=? (blue-eyed-descendant? Eva) true)(boolean=? (blue-eyed-descendant? Bettina) true)
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• Template:
• Current person can be checked immediately
50
(define (blue-eyed-descendant? a-parent) ... (parent-children a-parent) ... ... (parent-name a-parent) ... ... (parent-date a-parent) ... ... (parent-eyes a-parent) ... )
(define (blue-eyed-descendant? a-parent) (cond [(symbol=? (parent-eyes a-parent) 'blue) true] [else ... (parent-children a-parent) ... ... (parent-name a-parent) ... ... (parent-date a-parent) ...]))
Name and date of birth are unimportant for this task
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• We need a procedure which browses a list of children in
search of blue-eyed descendants• Following our guideline for complex procedures, we add such
a procedure to our wish list:
• Now we can finish blue-eyed-descendant?:
51
;; blue-eyed-children? : list-of-children -> boolean;; to determine whether any of the structures ;; on aloc is blue-eyed or has any blue-eyed descendant(define (blue-eyed-children? aloc) ...)
(define (blue-eyed-descendant? a-parent) (cond [(symbol=? (parent-eyes a-parent) 'blue) true] [else (blue-eyed-children? (parent-children a-parent))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• Processing the wish list:
– Creation of blue-eyed-children? • Standard template for lists:
• List is empty trivial• Result of the recursive call needs only be linked with “or”, to
check if the first element of the list has a blue-eyed descendant
• We just need a procedure which computes if a descendant has blue eyes, given a parent structure– This procedure is blue-eyed-descendant?
52
(define (blue-eyed-children? aloc) (cond [(empty? aloc) ...] [else ... (first aloc) ... ... (blue-eyed-children? (rest aloc)) ...]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures
• Final result
53
;; blue-eyed-children? : list-of-children -> boolean;; to determine whether any of the structures in aloc;; is blue-eyed or has any blue-eyed descendant
(define (blue-eyed-children? aloc) (cond [(empty? aloc) false] [else (or (blue-eyed-descendant? (first aloc)) (blue-eyed-children? (rest aloc)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Mutually Recursive Structures• Lesson learned:
– Reason: The structure of the procedure should always follow the structure of the data!
– Mutually recursive data should always be treated as a single unit, since they only make sense that way
– Implement procedures on mutually recursive data by using the wish list approach
• Due to the mutual dependencies, strict bottom-up or top-down implementation is not possible!
54
Procedures operating on mutually recursive data structures are mutually recursive themselves!
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Intermezzo
Iterative refinement of programs
55
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Iterative refinement of programs• While we are programming, we create a model of
a small part of the real world– When we start, it is often not clear which
aspects/information should be included in the model• Because of this, we should proceed iteratively, i.e.
improve the program and data concept stepwise– Start with a very simple model– Add details step by step
• Our example: Iterative refinement of a data model for file systems
56
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Iterative refinement of programs• Example of a file system structure
57
TS (DIR)
Text (DIR) Libs (DIR)
Code(DIR)
Docs (DIR)
part1 (99)
part2 (52)
part3 (17)
read! (10)
read! (19)
draw (2)hang (8)
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Iterative refinement of programs• Model 1:
– Files are represented by the name of the file (symbol); – A directory is a list made up of files and directories
• Data model:
58
A file is a symbol
A directory (short: dir) is either empty, or (cons f d) where f is a file and d is a directory; or (cons d1 d2) where d1 and d2 are dirs.
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Iterative refinement of programs• Model 2:
– A directory has a name and other attributes which we want to model
• Improved Data model: – (define-struct dir (name content)
– Both data structures are mutually recursive!
59
A directory (short: dir) is a structure (make-dir n c), where n is a symbol and c is a list of files and directories
A list of files and directories (LOFD) is either1. empty2. (cons f d) where f is a file and d is a LOFD 3. (cons d1 d2) whereas d1 is a dir and d2 is a LOFD
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Iterative refinement of programs• Model 3:
– We also want to model the attributes of files (size, content)
– We want to be able to distinguish between files and directories
• Improved Data model :– (define-struct file (name size content))
60
A list of files (LOF) is either1. empty2. (cons f lof) where f is a file and lof is a LOF
A file is a structure (make-file name size content), where name is a symbol, size is a number and content is a string
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Iterative refinement of programs• Model 3:…
• Improved Data model, continued:– (define-struct dir (name dirs files))
61
A directory (short: dir) is a structure(make-dir name dirs files),where name is a symbol, dirs
is a LOD and files is a LOF
A list of directories (LOD) is either1. empty2. (cons d lod) where d is a dir and lod is a LOD
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
62
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
• Up to now we have only seen procedures that accept one complex argument– ‘complex’ means: The data type of the argument is
defined recursively• For two or more complex arguments, there are
three cases to consider:1. One of the arguments can be treated as atomic for the
purpose of the procedure2. All arguments are processed synchronously3. All possible cases of the input arguments must be
treated separately • We will now look at one example for each of these
cases
63
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
1. example: One argument is treated as atomic– Recursion happens only for first argument
64
;; append : list list -> list;; to construct a new list by replacing empty ;; in alon1 with alon2
(define (append alon1 alon2) (cond ((empty? alon1) alon2) (else (cons (first alon1) (append (rest alon1) alon2)))))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
2. example: All arguments are processed synchronously
65
;; addlist : ;; list-of-numbers list-of-numbers -> list-of-numbers;; to construct a new list of numbers where the i-th number;; is the sum of the i-th number of alon1 and the i-th ;; number of alon2;;;; Example: (addlist (list 1 2) (list 7 8 9)) (list 8 10)
(define (addlist alon1 alon2) (cond [(or (empty? alon1) (empty? alon2)) empty] [else (cons (+ (first alon1) (first alon2)) (addlist (rest alon1) (rest alon2)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
3. Example: All possible cases of the input arguments must be treated separately
• Examples:
66
;; list-pick : list-of-symbols N[>= 1] -> symbol;; to determine the nth symbol from alos, counting from 1;;; signals an error if there is no n-th item(define (list-pick alos n) ...)
(list-pick empty 1) ;; expected behavior: (error 'list-pick "...")
(list-pick (cons 'a empty) 1);; expected value: 'a
(list-pick empty 3) ;; expected behavior: (error 'list-pick "...")
(list-pick (cons 'a empty) 3);; expected behavior: (error 'list-pick "...")
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
• 3. example: All possible cases of the input arguments must be treated separately
• Obviously, there are four interesting cases:
67
(empty? alos) (cons? alos)
(= n 1) (and (= n 1) (empty? alos))
(and (= n 1) (cons? alos))
(> n 1) (and (> n 1) (empty? alos))
(and (> n 1) (cons? alos))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
• Transferring the different cases to the procedure design
• Now, each case can be implemented individually
68
define (list-pick alos n) (cond [(and (= n 1) (empty? alos)) ...] [(and (> n 1) (empty? alos)) ... (sub1 n) ...] [(and (= n 1) (cons? alos)) ... (first alos) ... (rest alos)...] [(and (> n 1) (cons? alos)) ... (sub1 n) ... (first alos) ... (rest alos) ...]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
• Complete implementation
– Works, but the procedure can be simplified!– Next step for such procedures
• Analyze the cases and look for possible simplifications
69
;; list-pick : list-of-symbols N[>= 1] -> symbol;; to determine the nth symbol from alos, counting from 1;;; signals an error if there is no nth item(define (list-pick alos n) (cond [(and (= n 1) (empty? alos)) (error 'list-pick "list too short")] [(and (> n 1) (empty? alos)) (error 'list-pick "list too short")] [(and (= n 1) (cons? alos)) (first alos)] [(and (> n 1) (cons? alos)) (list-pick (rest alos) (sub1 n))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
• Cases 1 and 2 have the same implementation
• Simplified implementation:
70
(define (list-pick alos n) (cond [(and (= n 1) (empty? alos)) (error 'list-pick "list too short")] [(and (> n 1) (empty? alos)) (error 'list-pick "list too short")] [(and (= n 1) (cons? alos)) (first alos)] [(and (> n 1) (cons? alos)) (list-pick (rest alos) (pred n))]))
(define (list-pick alos n) (cond [(or (and (= n 1) (empty? alos)) (and (> n 1) (empty? alos)))
(error 'list-pick "list too short")] [(and (= n 1) (cons? alos)) (first alos)] [(and (> n 1) (cons? alos)) (list-pick (rest alos) (pred n))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Procedures with many complex arguments
• A “close look” (rules of logic) at the code reveals that the first condition can be reduced to (empty? alos)– As a result, we can omit the cons-condition from cases 2 and
3• Final version:
71
(define (list-pick alos n) (cond [(empty? alos) (error 'list-pick "list too short")] [(= n 1) (first alos)] [(> n 1) (list-pick (rest alos) (sub1 n))]))
(define (list-pick alos n) (cond [(or (and (= n 1) (empty? alos)) (and (> n 1) (empty? alos)))
(error 'list-pick "list too short")] [(and (= n 1) (cons? alos)) (first alos)] [(and (> n 1) (cons? alos)) (list-pick (rest alos) (sub1 n))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• In the following, we look at a larger example, which
illustrates the methods learned in this lecture• At the same time, this program is the first step towards a
Scheme interpreter written in Scheme– making the evaluation rules more concrete!
• Task: – representation and computation of any nested arithmetic
expression consisting of multiplication and addition• Input: “deep” list of symbols and numbers
– For example, '(+ 3 (* (+ 3 5) (* 1 2)))) = (list '+ 3 (list '* (list '+ 3 5) (list '* 1 2)))
= (cons '+ (cons 3 (cons (cons '* (cons (cons '+ (cons 3 (cons 5 empty)))
(cons (cons '* (cons 1 (cons 2 empty))) empty))) empty)))
• Output: value representing the arithmetic expression
72
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions1. step: data analysis• Design of a data structure for arithmetic
expressions– In principle, we could work directly with the deep lists of
symbols/numbers (so-called “s-expressions”)– This gets complex very quickly, because s-expressions
are too general• e.g., we just want to consider double-digit operators, but
there are only lists for s-expressions– Furthermore, we must always be prepared for wrong
inputs• Therefore, we will define our own data structure
for storing arithmetic data, and convert the s-expressions to this structure– This is called “parsing” 73
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Definition of the data type “aexp”:
74
;; Data definition:;; An arithmetic expression aexp is either;; 1. a number;; 2. (make-add l r) where l and r are aexp;; 3. (make-mul l r) where l and r are aexp
(define-struct add (left right))(define-struct mul (left right))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Definition of the parser
75
;; parse :: deep-list-of symbol -> aexp;; converts a deep list of symbols into a corresponding;; aexp, if possible;; ;; Example: ;; (parse '(+ 3 (* (+ 3 5) (* 1 2))));; = (make-add 3 (make-mul (make-add 3 5) (make-mul 1 2)))(define (parse sexp) (cond [(number? sexp) sexp] [(cons? sexp) (cond [(symbol=? (first sexp) '+)
(make-add (parse (second sexp)) (parse (third sexp)))] [(symbol=? (first sexp) '*) (make-mul (parse (second sexp)) (parse (third sexp)))])]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Definition of the evaluation Procedure
76
;; calc :: aexp -> number;; calculates the number represented by ;; the arithmetic expression exp;;;; Example:;; (calc (make-add 3 (make-mul (make-add 3 5) (make-mul 1 2))));; = 19(define (calc exp) (cond [(number? exp) exp) [(add? exp) (+ (calc (add-left exp)) (calc (add-right exp)))] [(mul? exp) (* (calc (mul-left exp)) (calc (mul-right exp)))]))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Usage of the interpreter:
– e.g. (calc (parse ‘(+ 5 (* 7 3)))) 26• What is this program good for?
– Good example of recursive data structures and recursive functions that operate on them
– We have just implemented a (primitive) interpreter• it interprets the language of the arithmetic expression
– It models how Scheme itself interprets arithmetic expressions
– The basic structure of this mini-interpreter is already the same as the structure of a “full-grown” interpreter for a language like Scheme
• Parser, recursively defined data structure, recursively defined evaluation procedure
– Later, we will extend the interpreter so that it can interpret the substantial parts of the language Scheme!
77
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Take a look at the code from the Software
Engineering point of view: – How extensible is it?
• Two important dimensions for extensibility:– Adding new data types (e.g. Div, Sub)– Adding new operations (e.g. scale)
• Adding new operations is easy:– No existing code must be changed!
78
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Adding a new operation
79
;; swap+* :: aexp -> aexp;;;; generates new aexp within which;; every addition is replaced by multiplication;; and vice versa;;;; Example:;; (swap+* (make-add 3 (make-mul 5 7)));; = (make-mul 3 (make-add 5 7))(define (swap+* exp) (cond ((number? exp) exp) ((add? exp) (make-mul (swap+* (add-left exp)) (swap+* (add-right exp)))) ((mul? exp) (make-add (swap+* (mul-left exp)) (swap+* (mul-right exp))))))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Take a look at the code from the Software
Engineering point of view: – How extensible is it?
• Two important dimensions for extensibility:– Adding new data types (e.g. Div, Sub)– Adding new operations (e.g. scale)
• Adding new operations is easy:– No existing code must be changed!
• But adding new data types is hard:– the cond-statements of all operations must be extended
by one case for each new data type80
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions
• Adding a new data type
81
;; Data definition:;; An arithmetic expression aexp is either;; 1. a number;; 2. (make-add l r) where l and r are aexp;; 3. (make-mul l r) where l and r are aexp;; 4. (make-sub l r) where l and r are aexp
(define-struct add (left right))(define-struct mul (left right))(define-struct sub (left right))
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Adding a new data type
82
;; calc :: aexp -> number;; …(define (calc exp) (cond ((number? exp) exp) ((add? exp) (+ (calc (add-left exp)) (calc (add-right exp)))) ((sub? exp) (- (calc (add-left exp)) (calc (add-right exp)))) ((mul? exp) (* (calc (mul-left exp)) (calc (mul-right exp))))))
Existing code must be changed.Analogous: other operations such as swap+*
Dr. G. RößlingProf. Dr. M. MühlhäuserRBG / Telekooperation
©
Introduction to Computer Science I: T3
Analyzing arithmetic expressions• Take a look at the code from the Software Engineering point
of view: – How extensible is it?
• Two important dimensions for extensibility:– Adding new data types (e.g. Div, Sub)– Adding new operations (e.g. scale)
• Adding new operations is easy:– No existing code must be changed!
• But adding new data types is hard:– the cond-statements of all operations must be extended
by one case for each new data type– Existing code must be changed; this is bad, in particular if the
different parts of the code should be developed independently from each other
• Later, we will see that the situation in object-oriented languages is exactly inverted!
83