CS320: Recursion and Lazy Evaluation Sukyoung Ryu March 12, 2012 0
CS320:
Recursion and Lazy EvaluationSukyoung RyuMarch 12, 2012
CS320: Recursion and Lazy Evaluation
Midterm
March 28th Wednesday 11AM1PM
1
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion?
2
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion? 1 (n 1)! n 0 1 F n1 + Fn2 if n = 0 if n > 0 if n = 0 if n = 1 if n > 1
n! =
Fn =
3
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion in this way?
4
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion in this way?Denition: a method where the solution to a problem depends on solutions to smaller instances of the same problem.a > Examples:factorial(n) = if n = 0 then 1 else factorial(n-1) * n fibonacci(n) = if n = 0 then 1 else if n = 1 then 1 else fibonacci(n-1) + fibonacci(n-2)> >
Interpreter: Dene a small language with recursion and implement its interpreter to see how it actually works.
L. Graham, Donald E. Knuth, and Oren Patashnik (1990). Concrete Mathematics. Chapter 1: Recurrent Problems.
a Ronald
5
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion in this way? > Because DrRacket does not support recursion?
6
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion in this way? > Because DrRacket does not support recursion?; interp : AE -> number (define (interp an-ae) (type-case AE an-ae [num (n) n] [add (l r) (+ (interp l) (interp r))] [sub (l r) (- (interp l) (interp r))]))
7
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion in this way? > Why not just use recursion supported by DrRacket? Why bother use dummy values for functions?
8
CS320: Recursion and Lazy Evaluation
Questions and Answers Why do we learn recursion in this way? > Why not just use recursion supported by DrRacket? Why bother use dummy values for functions? > DrRacket denes recursive functions by define and RCFAE denes recursive functions by rec. > DrRacket looks up recursive functions from its internal symbol table and RCFAE looks up recursive functions from DefrdSub.
9
CS320: Recursion and Lazy Evaluation
RCFAE: Concrete Syntax ::= | {+ } | {- } | | {fun {} } | { } | {if0 } | {rec { } }
10
CS320: Recursion and Lazy Evaluation
RCFAE: Abstract Syntax(define-type RCFAE [num (n number?)] [add (lhs RCFAE?) (rhs RCFAE?)] [sub (lhs RCFAE?) (rhs RCFAE?)] [id (name symbol?)] [fun (param symbol?) (body RCFAE?)] [app (fun-expr RCFAE?) (arg-expr RCFAE?)] [if0 (test-expr RCFAE?) (then-expr RCFAE?) (else-expr RCFAE?)] [rec (name symbol?) (named-expr RCFAE?) (body RCFAE?)])
11
CS320: Recursion and Lazy Evaluation
RCFAE: Interpreter; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae [num (n) (numV n)] [add (l r) (num+ (interp l ds) (interp r ds))] [sub (l r) (num- (interp l ds) (interp r ds))] [id (name) (lookup name ds)] [fun (param body-expr) (closureV param body-expr ds)] [app (f a) (local [(define ftn (interp f ds))] (interp (closureV-body ftn) (aSub (closureV-param ftn) (interp a ds) (closureV-ds ftn))))] [if0 (c t e) (if (numzero? (interp c ds)) (interp t ds) (interp e ds))] [rec (bound-id named-expr body-expr) ...]))
12
CS320: Recursion and Lazy Evaluation
RCFAE: Interpreter; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae ... [rec (bound-id named-expr body-expr) ...]))
13
CS320: Recursion and Lazy Evaluation
RCFAE: Interpreter; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae ... [rec (bound-id named-expr body-expr) ... (interp named-expr ds) ... (interp body-expr ds) ...]))
14
CS320: Recursion and Lazy Evaluation
RCFAE: Interpreter; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae ... [rec (bound-id named-expr body-expr) (local [(define new-ds (aRecSub bound-id ... ds))] ... (interp named-expr new-ds) ... (interp body-expr new-ds) ...)]))
15
CS320: Recursion and Lazy Evaluation
RCFAE: Interpreter; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae ... [rec (bound-id named-expr body-expr) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub bound-id value-holder ds))] ... (interp named-expr new-ds) ... (interp body-expr new-ds) ...]))
16
CS320: Recursion and Lazy Evaluation
RCFAE: Interpreter; interp : RCFAE DefrdSub -> RCFAE-Value (define (interp rcfae ds) (type-case RCFAE rcfae ... [rec (bound-id named-expr body-expr) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub bound-id value-holder ds))] (begin (set-box! value-holder (interp named-expr new-ds)) (interp body-expr new-ds)))]))
17
CS320: Recursion and Lazy Evaluation
RCFAE: DefrdSub(define-type DefrdSub [mtSub] [aSub (name symbol?) (value RCFAE-Value?) (ds DefrdSub?)] [aRecSub (name symbol?) (value-box (box/c RCFAE-Value?)) (ds DefrdSub?)]) (define-type RCFAE-Value [numV (n number?)] [closureV (param Symbol?) (body RCFAE?) (ds DefrdSub?)])
18
CS320: Recursion and Lazy Evaluation
RCFAE: Lookup; lookup : symbol DefrdSub -> num (define (lookup name ds) (type-case DefrdSub ds [mtSub () (error lookup "free variable")] [aSub (sub-name val rest-ds) (if (symbol=? sub-name name) val (lookup name rest-ds))] [aRecSub (sub-name val-box rest-ds) (if (symbol=? sub-name name) (unbox val-box) (lookup name rest-ds))]))
19
CS320: Recursion and Lazy Evaluation
Boxes in DrSchemeA box is like a single-element vector, normally used as minimal mutable storage. http://docs.racket-lang.org/reference/boxes.html box:(define value-holder (box (numV 42))) (set-box! value-holder (interp named-expr new-ds))
set-box!: unbox: box/c:
(unbox val-box) (value-box (box/c RCFAE-Value?))
20
CS320: Recursion and Lazy Evaluation
Example Run!
(run "{rec {count {fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}} {count 8}}" (mtSub))
21
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (run "{rec {count {fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}} {count 8}}" (mtSub))
22
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (run "{rec {count {fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}} {count 8}}" (mtSub)) f fun-expr body value-holder new-ds = = = = =23
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (run "{rec {count {fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}} {count 8}}" (mtSub)) f fun-expr body value-holder new-ds = = = = = "count" "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" "{count 8}" [numV 42] (aRecSub count value-holder (mtSub))24
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (interp fun-expr new-ds) fun-expr body value-holder new-ds = = = = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" "{count 8}" [numV 42] (aRecSub count value-holder (mtSub))
25
CS320: Recursion and Lazy Evaluation
Example Run!
[fun (param body-expr) (closureV param body-expr ds)] (interp fun-expr new-ds) fun-expr body value-holder new-ds = = = = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" "{count 8}" [numV 42] (aRecSub count value-holder (mtSub))
26
CS320: Recursion and Lazy Evaluation
Example Run!
[fun (param body-expr) (closureV param body-expr ds)] (interp fun-expr new-ds) fun-expr = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" body = "{count 8}" value-holder = [numV 42] new-ds = (aRecSub count value-holder (mtSub)) (interp fun-expr new-ds) = (closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)
27
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (interp fun-expr new-ds) fun-expr = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" body = "{count 8}" value-holder = [numV 42] new-ds = (aRecSub count value-holder (mtSub)) (interp fun-expr new-ds) = (closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)
28
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (set-box! value-holder (interp fun-expr new-ds)) fun-expr = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" body = "{count 8}" value-holder = [numV 42] new-ds = (aRecSub count value-holder (mtSub)) (interp fun-expr new-ds) = (closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)
29
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (set-box! value-holder (interp fun-expr new-ds)) fun-expr = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" body = "{count 8}" value-holder = [(closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)] new-ds = (aRecSub count value-holder (mtSub)) (interp fun-expr new-ds) = (closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)
30
CS320: Recursion and Lazy Evaluation
Example Run![rec (f fun-expr body) (local [(define value-holder (box (numV 42))) (define new-ds (aRecSub f value-holder ds))] (begin (set-box! value-holder (interp fun-expr new-ds)) (interp body new-ds)))] (interp body new-ds) fun-expr = "{fun {n} {if0 n 0 {+ 1 {count {- n 1}}}}}" body = "{count 8}" value-holder = [(closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)] new-ds = (aRecSub count value-holder (mtSub)) (interp fun-expr new-ds) = (closureV n "{if0 n 0 {+ 1 {count {- n 1}}}}" new-ds)
31
CS320: Recursion and Lazy Evaluation
Lazy Evaluation
32
CS320: Recursion and Lazy Evaluation
Scheme vs. AlgebraIn Scheme, we have a specic order for evaluating subexpressions: (+ (* 4 3) (- 8 7)) (+ 12 (- 8 7)) (+ 12 1) In Algebra, order does not matter: (4 3) + (8 7) 12 + (8 7) 12 + 1 or: (4 3) + (8 7) (4 3) + 1 12 + 1
33
CS320: Recursion and Lazy Evaluation
Algebraic ShortcutsIn Algebra, if we see: f (x, y ) = x g (z ) = . . . f (17, g (g (g (g (g (18)))))) then we can go straight to: 17 because the result of all the g calls will not be used.
34
CS320: Recursion and Lazy Evaluation
Lazy Evaluation Languages like Scheme, Java, and C are called eager > An expression is evaluated when it is encountered Languages that avoid unnecessary work are called lazy > An expression is evaluated only if its result is needed
35
CS320: Recursion and Lazy Evaluation
LFAE = Lazy FAE ::= | | | | | {+ } {- } {fun {} } { }
36
CS320: Recursion and Lazy Evaluation
LFAE = Lazy FAE ::= | | | | | {+ } {- } {fun {} } { }
{{fun {x} 0} {+ 1 {fun {y} 2}}} {{fun {x} x} {+ 1 {fun {y} 2}}}
37
CS320: Recursion and Lazy Evaluation
LFAE = Lazy FAE ::= | | | | | {+ } {- } {fun {} } { }
{{fun {x} 0} {+ 1 {fun {y} 2}}} 0 {{fun {x} x} {+ 1 {fun {y} 2}}} error
38
Sukyoung [email protected] http://plrg.kaist.ac.kr