Sei sulla pagina 1di 40

CS320:

Recursion and Lazy Evaluation


Sukyoung Ryu
March 12, 2012

CS320: Recursion and Lazy Evaluation

Midterm

March 28th Wednesday 11AM1PM

CS320: Recursion and Lazy Evaluation

Questions and Answers


Why do we learn recursion?

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 =

CS320: Recursion and Lazy Evaluation

Questions and Answers


Why do we learn recursion in this way?

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

CS320: Recursion and Lazy Evaluation

Questions and Answers


Why do we learn recursion in this way? > Because DrRacket does not support recursion?

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))]))

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?

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.

CS320: Recursion and Lazy Evaluation

RCFAE: Concrete Syntax


<RCFAE> ::= <num> | {+ <RCFAE> <RCFAE>} | {- <RCFAE> <RCFAE>} | <id> | {fun {<id>} <RCFAE>} | {<RCFAE> <RCFAE>} | {if0 <RCFAE> <RCFAE> <RCFAE>} | {rec {<id> <RCFAE>} <RCFAE>}

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 DrScheme
A 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. Algebra


In 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 Shortcuts
In 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


<LFAE> ::= | | | | | <num> {+ <LFAE> <LFAE>} {- <LFAE> <LFAE>} <id> {fun {<id>} <LFAE>} {<LFAE> <LFAE>}

36

CS320: Recursion and Lazy Evaluation

LFAE = Lazy FAE


<LFAE> ::= | | | | | <num> {+ <LFAE> <LFAE>} {- <LFAE> <LFAE>} <id> {fun {<id>} <LFAE>} {<LFAE> <LFAE>}

{{fun {x} 0} {+ 1 {fun {y} 2}}} {{fun {x} x} {+ 1 {fun {y} 2}}}

37

CS320: Recursion and Lazy Evaluation

LFAE = Lazy FAE


<LFAE> ::= | | | | | <num> {+ <LFAE> <LFAE>} {- <LFAE> <LFAE>} <id> {fun {<id>} <LFAE>} {<LFAE> <LFAE>}

{{fun {x} 0} {+ 1 {fun {y} 2}}} 0 {{fun {x} x} {+ 1 {fun {y} 2}}} error

38

Sukyoung Ryu
sryu.cs@kaist.ac.kr http://plrg.kaist.ac.kr

Potrebbero piacerti anche