Evaluation strategies. Applications of lazy evaluation Evaluation strategies. Applications of lazy evaluation Purpose of this lecture Clarify the following notions: Evaluation strategies applicative (or eager) evaluation versus lazy evaluation H ASKELL versus R ACKET Lazy evaluation in R ACKET with functional closures with promises Applications: streams Natural numbers Fibonacci numbers Prime numbers Evaluation strategies. Applications of lazy evaluation Evaluation strategies 1. Applicative (or eager) evaluation Arguments are evaluated before being passed to function calls Example (λx.λy .(x + y ) 1 (λz.(z + 2) 3)) = (λx.λy .(x + y ) 1 5) = λy .(1 + y ) 5 = 6. Evaluation strategies. Applications of lazy evaluation Evaluation strategies 1. Applicative (or eager) evaluation Arguments are evaluated before being passed to function calls Example (λx.λy .(x + y ) 1 (λz.(z + 2) 3)) = (λx.λy .(x + y ) 1 5) = λy .(1 + y ) 5 = 6. Remarks With this evaluation strategy, all function calls receive values as arguments Therefore, it is also known as call by value evaluation R ACKET and all imperative languages perform applicative evaluation of function calls. Evaluation strategies. Applications of lazy evaluation Evaluation strategies Lazy evaluation The evaluation of an expression is delayed until it is really needed. Example (λx.λy .(x + y ) 1 (λz.(z + 2) 3)) = (λy .(1 + y ) (λz.(z + 2) 3)) = 1 + (λz.(z + 2) 3) = 1 + 5 = 6. Evaluation strategies. Applications of lazy evaluation Evaluation strategies Lazy evaluation The evaluation of an expression is delayed until it is really needed. Example (λx.λy .(x + y ) 1 (λz.(z + 2) 3)) = (λy .(1 + y ) (λz.(z + 2) 3)) = 1 + (λz.(z + 2) 3) = 1 + 5 = 6. Remarks The function call (λz.(z + 2) 3) is sent as parameter, and its evaluation is delayed until needed. H ASKELL is a functional programming language with lazy evaluation strategy. Evaluation strategies. Applications of lazy evaluation Eager versus Lazy evaluation Which one is better? Both have advantages and disadvantages. Disadvantages of eager evaluation B May perform some useless computations B May run never-ending computations (see example) Disadvantages of lazy evaluation: B Some computations can be duplicated Example Let fix = λf .(f (fix f )) and ct = λx.1. Eager evaluation of fix ct runs forever: fix ct = ct (fix ct) = ct (ct (fix ct)) = . . . Lazy evaluation of fix ct stops immediately: fix ct = ct (fix ct) = 1 Evaluation strategies. Applications of lazy evaluation Lazy evaluation in R ACKET Although R ACKET has applicative evaluation strategy, we can simulate lazy evaluation in two ways: 1 With nullary functional closures A nullary functional closure is a created by a lambda expression with zero arguments: (lambda () body) 2 with delay/force promises Evaluation strategies. Applications of lazy evaluation Lazy evaluation with nullary functional closures Main idea: To define a function with lazy evaluation, wrap its body in (lambda () ...) Example (Lazy version of sum) > (define sum (lambda (x y) (lambda () (+ x y)))) > (sum 1 2) #<procedure> >((sum 1 2)) 3 R EMARK : (sum 1 2) returns a function that expects 0 input arguments (that is, a nullary functional closure). A nullary function call of f is (f). Evaluation strategies. Applications of lazy evaluation Lazy evaluation with delay/force Example (delayed evaluation of sum) The conventional definition of sum is: > (define sum (lambda (x y) (+ x y))) To delay it’s evaluation, call > (define s (delay (sum 1 2))) > s #promise To perform a delayed computation c, call (force c): > (force s) 3 Evaluation strategies. Applications of lazy evaluation Lazy evaluation with delay/force Example (delayed version of sum) > (define sum (lambda (x y) (delay (+ x y)))) > (sum 1 2) #promise > (force (sum 1 2)) 3 Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Streams Stream: a finitely representation of an infinite list. Examples of infinite lists that can be represented by streams: All ones: (1 1 1 ...) Natural numbers: (0 1 2 3 ...) Fibonacci numbers: (1 1 2 3 5 8 13 ...) (f0 = f1 = 1 fn+2 = fn + fn+1 for all n ≥ 0) Prime numbers: (2 3 5 7 11 13 ...) Main idea of stream representation (a1 ... ak . gen) where gen is a generator that can be used to generate the rest of the stream. Typically, gen is either a nullary function or a promise. Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of all ones Implementation with nullary function as generator > (define make-ones (lambda () (cons 1 make-ones))) > (define all-ones (make-ones)) > ; extract list of first n elements from a stream (define (take n stream) (if (= n 0) null (if (pair? stream) (cons (car stream) (take (- n 1) (cdr stream))) (take n (stream))))) > (take 4 all-ones) ; test ’(1 1 1 1) Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of natural numbers starting from 0 Implementation with promises ; generator for natural numbers (define make-naturals (lambda (k) (cons k (delay (make-naturals (+ k 1)))))) ; stream of natural numbers starting from 0 (define all-naturals (make-naturals 0)) ; extract first n elements from the stream (define (take n stream) (if (= n 0) null (if (pair? stream) (cons (car stream) (take (- n 1) (cdr stream))) (take n (force stream))))) Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Streams Remarks The implementation details of a stream (with nullary functions, or with delay/force) should be hidden to the user. Exercise: Reimplement make-ones with delay/force, and all-naturals with nullary functions. Example: take that works on both kinds of implementation (define (take n stream) (if (= n 0) null (if (pair? stream) (cons (car stream) (take (- n 1) (cdr stream))) (take n (if (promise? stream) (force stream) (stream)))))) Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of Fibonacci numbers Useful observation: the stream fib of Fibonacci numbers has the following useful property: fib + (cdr fib) yields (cdr (cdr fib)) fib = f0 f1 f2 . . . + (cdr fib) = f1 f2 f3 . . . f0 f1 f2 f3 f4 . . . Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of Fibonacci numbers Useful observation: the stream fib of Fibonacci numbers has the following useful property: fib + (cdr fib) yields (cdr (cdr fib)) fib = f0 f1 f2 . . . + (cdr fib) = f1 f2 f3 . . . f0 f1 f2 f3 f4 . . . Once we know the first two elements f0 and f1 , we can start generating the rest of the stream: fib = (1 1 . gen) where the implementation of the generator gen implements the addition of streams fib with (cdr fib). Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of Fibonacci numbers (define fib (cons 1 (cons 1 (delay (add fib (cdr fib)))))) ; addition of two streams (define (add s1 s2) (if (promise? s1) (add (force s1) s2) (if (promise? s2) (add s1 (force s2)) (cons (+ (car s1) (car s2)) (delay (add (cdr s1) (cdr s2))))))) Test: > (take 10 fib) ’(1 1 2 3 5 8 13 21 34 55) Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of prime numbers Main idea: Erathostene’s sieve Consider the stream all all natural numbers starting with 2: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of prime numbers Main idea: Erathostene’s sieve Consider the stream all all natural numbers starting with 2: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... Remove all elements divisible with the first element of the stream, except the first element 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of prime numbers Main idea: Erathostene’s sieve Consider the stream all all natural numbers starting with 2: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... Remove all elements divisible with the first element of the stream, except the first element 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... Repeat this process on the tail of what is left: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... etc. Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Useful operations: filter and map of streams (myfilter pred stream) returns the stream of elements from stream for which pred holds. (mymap f stream) applies unary function f to all elements of stream (define myfilter (lambda (p s) (if (promise? s) (myfilter p (force s)) (if (p (car s)) (cons (car s) (delay (myfilter p (cdr s)))) (myfilter p (cdr s)))))) (define mymap (lambda (f s) (if (promise? s) (mymap f (force s)) (cons (f (car s)) (delay (mymap f (cdr s))))))) Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of prime numbers ; some auxiliary stuff (define (divides? x y) (zero? (remainder x y))) ; Erathostenes’ sieve (define (sieve s) (if (promise? s) (sieve (force s)) (cons (car s) (delay (sieve (myfilter (lambda (x) (not (divides? x (car s)))) (cdr s))))))) (define all-primes (sieve (make-naturals 2))) Evaluation strategies. Applications of lazy evaluation Applications of lazy evaluation Stream of prime numbers Tests > ; first 10 prime numbers (take 10 all-primes) ’(2 3 5 7 11 13 17 19 23 29) > ; first prime greater than 200 (car (myfilter (lambda (x) (> x 200)) all-primes)) 211 > ; first ten multiples of 5 (take 10 (mymap (lambda (x) (* 5 x)) all-naturals)) ’(0 5 10 15 20 25 30 35 40 45) > ; first ten elements of fib + all-primes (take 10 (add fib all-primes)) ’(3 4 7 10 16 21 30 40 57 84) Evaluation strategies. Applications of lazy evaluation
© Copyright 2026 Paperzz