Download as pdf or txt
Download as pdf or txt
You are on page 1of 5

Recommended 

Exercises and Readings
• From Haskell: The craft of functional programming (3rd Ed.)
• Exercises:
• 17.1, 17.2, 17.4, 17.8, 17.23, 17.25, 17.28, 17.29
Topic 8: Lazy Evaluation • Readings:
• Chapter 17.1, 17.2, 17.3, 17.6, 17.7

1 2

Lazy Evaluation Lazy Evaluation and Guards
• When lazy evaluation is employed… • Consider the following function and function calls
• Objects and expressions are evaluated when they are needed
• Expressions that are not used subsequently are not evaluated choice :: Int ‐> a ‐> a ‐> a ‐> a
• Haskell is lazy choice n x y z
| n > 0          = x
• In Haskell, lazy evaluation applies to | n == 0        = y
• Function parameters | otherwise = z
• List elements
• Guards choice 10 (naiveFib 29) (naiveFib 30) (naiveFib 31)
• Logical expressions choice 0   (naiveFib 29) (naiveFib 30) (naiveFib 31)
• … choice ‐2 (naiveFib 29) (naiveFib 30) (naiveFib 31)
3 4
Lazy Evaluation and Pattern Matching Lazy Evaluation
• Consider the following function and function calls • With lazy evaluation…
• Parameters are passed to the function without being evaluated
multiply :: Int ‐> Int ‐> Int • Parameters are evaluated in the called scope only as required
multiply 0 _ = 0 • Repeated uses of the same parameter in the called scope are only evaluated 
multiply _ 0 = 0 once
multiply x y = x * y • Composite parameters, such as lists and tuples, may only be partially 
evaluated
multiply (12 + 12) (15 * 15)
multiply 0 (naiveFib 40)
multiply (naiveFib 40) 0

5 6

Evaluation in Java, C++ and Python Evaluation in Java, C++ and Python
• In almost all circumstances, evaluation is eager • In C++, the optimizer can (sometimes) avoid fully evaluating 
• Expressions are fully evaluated in the calling scope before they are passed to  expressions that are never used subsequently
the function • Mark nFib as a const function
long nFib(long n) int main(int argc, char** argv)
{ {
long nFib(long n) __attribute__ ((const));
if (n == 0) return 0; cout << "Starting..." << endl;
if (n == 1) return 1; cout << "  0 * nFib(41) is " << multiply(0, nFib(41)) << endl;
return nFib(n‐1) + nFib(n‐2); cout << "  nFib(42) * 0 is " << multiply(nFib(42), 0) << endl; • Turn on optimization
} cout << "  nFib(39) * nFib(40) is " << multiply(nFib(39), nFib(40)) << endl;

long multiply(long x, long y) return 0; g++ ‐O lazy.cpp


{ }
if (x == 0) return 0;
if (y == 0) return 0; • This is a rather different (and limited) form of lazy evaluation from what 
return x * y; Haskell provides, but it provides some of the same benefits
} 7 8
Evaluation in Java, C++ and Python Example: Prime Numbers
• Exception to eager evaluation: Built‐in logical operators • How can we efficiently identify the first n prime numbers?
• The ‘and’ and ‘or’ operators in Java, C++, C and Python all use a limited form  • Possible strategy:
of lazy evaluation that is often referred to as ‘short‐circuit’ evaluation • Start at two and check each number in sequence
• If the left operand’s value conclusively determines the outcome of the logical  • If the number is prime, add it to the list of primes
expression then the right operand is not evaluated • Otherwise discard the number
• No matter what – even if it has side effects! • Repeat until n prime numbers have been identified
• What’s undesirable about this solution?

9 10

Sieve of Eratosthenes Sieve of Eratosthenes
• An efficient technique for identifying all prime numbers from 2..n 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
Starting from the beginning of the list 31 32 33 34 35 36 37 38 39 40
Repeat 41 42 43 44 45 46 47 48 49 50
Identify the next item in the list as prime 51 52 53 54 55 56 57 58 59 60
Remove all multiples of the first element from consideration 61 62 63 64 65 66 67 68 69 70
Until the next item is greater than or equal to n 71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
11 12
Sieve of Eratosthenes Sieve of Eratosthenes
• Implement the Sieve of Eratosthenes as a function • But recall that the problem we really want to solve is finding a certain 
• Parameter: n (an integer), the maximum value to test number of primes
• Return: a list of primes (integers) less than or equal to n • Because primes are not predictably spaced, we don’t know how many primes 
we will get when finding all primes from 2 up to n
• We could pick some value for n and hope that it is big enough; or
• We could use an infinite list…

13 14

Infinite Data Structures Summary
• Lazy evaluation permits infinitely large data structures • Evaluation in Haskell is performed differently than languages like C++, 
• As long as they are never fully evaluated Java and Python
• Evaluation is lazy rather than eager
• Expressions are not evaluated until they are needed
• Unused expressions are never evaluated
• Lazy evaluation permits the creation of (but not complete evaluation 
of) infinite data structures

15 16
Infinite Data Structures
• Another example: Pseudo‐random numbers

17

You might also like