plt-2002-2 9/8/2015 2.2-1 inductive sets of data programming language essentials 2nd edition chapter...
TRANSCRIPT
plt-2002-2 04/21/23 2.2-1
Inductive Sets of Data
Programming Language Essentials
2nd edition
Chapter 1.2 Recursively Specified Programs
plt-2002-2 04/21/23 2.2-2
Recursion
recursion can lead to divide-and-conquer:
solution for a small problem 'by hand'.
solution for a bigger problem by recursively invoking the solution for smaller problems.
Examples:
Factorial.
Greatest common divisor (Euclid).
Tower of Hanoi.
Quicksort.
plt-2002-2 04/21/23 2.2-3
Recursively Specified Programs
patterned after proof by induction.
to compute xn:
e(0, x) = 1, because x0 is 1.
e(n, x) = x * e(n-1, x), because xn is x * xn-1.
induction proves that e(n,x) is xn:
(0) Hypothesis: e(k, x) is xk.
(1) true for k=0, see above.
(2) assume true up to k. Consider e(k+1, x).
This is x * e(k, x) by definition, x * xk by assumption, and therefore xk+1.
plt-2002-2 04/21/23 2.2-4
Recursively Specified Programs (2)
to compute xn:
e(0, x) = 1, because x0 is 1.
e(n, x) = x * e(n-1, x), because xn is x * xn-1.
(define e
(lambda (n x)
(if (zero? n)
1
(* x
(e (- n 1) x)
) ) ) )
plt-2002-2 04/21/23 2.2-5
count-nodesbintree: 'Number'
| '(' 'Symbol' bintree bintree ')'
(define count-nodes
(lambda (bintree)
(if (number? bintree)
1
(+ (count-nodes (cadr bintree))
(count-nodes (caddr bintree))
1
) ) ) )
plt-2002-2 04/21/23 2.2-6
Deriving Programs from BNFl-of-nums: '()'l-of-nums: '(' 'Number' '.' l-of-nums ')'
pattern program after data (structural induction)one procedure for one nonterminal
(define list-of-numbers? (lambda (x) (if (null? x) #t (and (pair? x) (number? (car x)) (list-of-numbers? (cdr x))) ) ) )
plt-2002-2 04/21/23 2.2-7
Proof by Induction
(0) Hypothesis: l-of-n? works on lists of length k.
(1) k=0: empty list, l-of-n? returns true. ok.
(2) assume true up to k. Consider k+1.
By grammar, car must be a number and cdr a list of numbers.
cdr of list of k+1 elements has k elements, i.e.,
l-of-n? can be applied. ok.
proof does not discover that pair? is necessary
because proof assumes list arguments
plt-2002-2 04/21/23 2.2-8
nth-elt
like list-ref, returns 0..th element of list.
(define nth-elt
(lambda (list n)
(if (null? list)
(error 'nth-elt "List too short."
(+ n 1) "elements")
(if (zero? n)
(car list)
(nth-elt (cdr list) (- n 1))
) ) ) )
plt-2002-2 04/21/23 2.2-9
errorhttp://srfi.schemers.org/
lists Scheme Request for Implementation
$ scheme48> ,open srfi-23Newly accessible in user: (error)> (define nth-elt …> (nth-elt '(1 2 3) -4)
Error: nth-elt "List too short." -6 "elements"
plt-2002-2 04/21/23 2.2-10
list-length
like length, returns number of elements in list
(define list-length
(lambda (list)
(if (null? list)
0
(+ 1 (list-length (cdr list)))
) ) )
plt-2002-2 04/21/23 2.2-11
fragile vs. robustfragile procedures do not check the types of their
arguments.
(define list-length ; robust version (lambda (list) (if (list? list) (if (null? list) 0 (+ 1 (list-length (cdr list))) ) (error 'list-length "Not a list:" list)) ) )
plt-2002-2 04/21/23 2.2-12
remove-first
returns list without first occurrence of symbol
list: '()' | '(' symbol '.' list ')'
(define remove-first ; fragile
(lambda (symbol list)
(if (null? list)
list
…
) ) )
plt-2002-2 04/21/23 2.2-13
remove-first
returns list without first occurrence of symbol
list: '()' | '(' symbol '.' list ')'
(define remove-first ; fragile
(lambda (symbol list)
(if (null? list)
list
(if (eqv? (car list) symbol)
(cdr list)
…
) ) ) )
plt-2002-2 04/21/23 2.2-14
remove-first
returns list without first occurrence of symbol
list: '()' | '(' symbol '.' list ')'
(define remove-first ; fragile
(lambda (symbol list)
(if (null? list)
list
(if (eqv? (car list) symbol)
(cdr list)
(cons (car list)
(remove-first symbol (cdr list))
) ) ) ) )
plt-2002-2 04/21/23 2.2-15
remove
returns list without all occurrences of symbol
list: '()' | '(' symbol '.' list ')'
(define remove ; fragile
(lambda (symbol list)
(if (null? list)
list
(if (eqv? (car list) symbol)
(remove symbol (cdr list))
(cons (car list)
(remove symbol (cdr list))
) ) ) ) )
plt-2002-2 04/21/23 2.2-16
substreturns s-list with any old replaced by new> (subst 'a 'b '((b c) (b () d)))'((a c) (a () d))
s-list: '(' symbol-expression* ')'symbol-expression: 'Symbol' | s-list
s-list: '()' | '(' symbol-expression '.' s-list ')'symbol-expression: 'Symbol' | s-list
pair avoids need for another rule
plt-2002-2 04/21/23 2.2-17
substs-list: '()'
| '(' symbol-expression '.' s-list ')'
(define subst ; fragile
(lambda (new old slist)
(if (null? slist)
slist
(cons
(subst-se new old (car slist))
(subst new old (cdr slist))
) ) ) )
plt-2002-2 04/21/23 2.2-18
subst-sesymbol-expression: 'Symbol' | s-list
(define subst-se
(lambda (new old se)
(if (symbol? se)
(if (eqv? se old) new se)
(subst new old se)
) ) )
mutual recursion
divide-and-conquer because of grammar
plt-2002-2 04/21/23 2.2-19
subst(define subst ; fragile
(lambda (new old slist)
(define symbol-expression ; local procedure
(lambda (se) ; shares parameters
(if (symbol? se)
(if (eqv? se old) new se)
(subst new old se)
) ) )
(if (null? slist)
slist
(cons
(symbol-expression (car slist))
(subst new old (cdr slist))
) ) ) )
plt-2002-2 04/21/23 2.2-20
notate-depth
returns s-list with symbols annotated for depth> (notate-depth '((b c) (b () d)))
'(((b 1) (c 1)) ((b 1) () (d 1)))
notate-depth: s-list
s-list: '()'
| '(' symbol-expression '.' s-list ')'
symbol-expression: 'Symbol' | s-list
notate-depth needed to mark start at level zero
plt-2002-2 04/21/23 2.2-21
notate-depthnotate-depth: s-list
(define notate-depth ; fragile (lambda (slist) (s-list slist 0)) )
plt-2002-2 04/21/23 2.2-22
notate-depths-list: '()' | '(' symbol-expression '.' s-list ')'
(define notate-depth (lambda (slist) (define s-list (lambda (slist d) (if (null? slist) slist (cons (symbol-expression (car slist) d) (s-list (cdr slist) d) ) ) ) ) (s-list slist 0)) )
plt-2002-2 04/21/23 2.2-23
notate-depthsymbol-expression: 'Symbol' | s-list
(define notate-depth
(lambda (slist)
(define s-list …
(define symbol-expression
(lambda (se d)
(if (symbol? se)
(list se d)
(s-list se (+ d 1))
) ) )
(s-list slist 0)
) )
plt-2002-2 04/21/23 2.2-24
notate-depth(define notate-depth (lambda (slist) (define s-list (lambda (slist d) (if (null? slist) slist (cons (symbol-expression (car slist) d) (s-list (cdr slist) d) ) ) ) ) (define symbol-expression (lambda (se d) (if (symbol? se) (list se d) (s-list se (+ d 1)) ) ) ) (s-list slist 0)) )
plt-2002-2 04/21/23 2.2-25
Other Patterns of Recursionl-of-nums: '()'
l-of-nums: '(' 'Number' '.' l-of-nums ')'
compute sum by structural induction:
(define list-sum
(lambda (x)
(if (null? x)
0
(+ (car x))
(list-sum (cdr x))
) ) ) )
plt-2002-2 04/21/23 2.2-26
Other Patterns of Recursion (2)vector is not suitable for structural induction, so:(define vector-sum (lambda (v) (partial-vector-sum v (vector-length v))) )(define partial-vector-sum (lambda (v n) (if (zero? n) 0 (+ (vector-ref v (- n 1)) ; last (partial-vector-sum v (- n 1))) ) ) )
plt-2002-2 04/21/23 2.2-27
Other Patterns of Recursion (3)(define vector-sum (lambda (v) (letrec ((partial-vector-sum (lambda (n) (if (zero? n) 0 (+ (vector-ref v (- n 1)) ; last (partial-vector-sum (- n 1)) ))) ) ) (partial-vector-sum (vector-length v))) ) )
proof by induction on vector length