functional programming - lazy evaluation

83
Functional Programming Lazy Evaluation H. Turgut Uyar 2013-2016

Upload: turgut-uyar

Post on 16-Feb-2017

286 views

Category:

Education


2 download

TRANSCRIPT

Page 1: Functional Programming - Lazy Evaluation

Functional ProgrammingLazy Evaluation

H. Turgut Uyar

2013-2016

Page 2: Functional Programming - Lazy Evaluation

License

© 2013-2016 H. Turgut Uyar

You are free to:

Share – copy and redistribute the material in any medium or format

Adapt – remix, transform, and build upon the material

Under the following terms:

Attribution – You must give appropriate credit, provide a link to the license, andindicate if changes were made.

NonCommercial – You may not use the material for commercial purposes.

ShareAlike – If you remix, transform, or build upon the material, you mustdistribute your contributions under the same license as the original.

For more information:https://creativecommons.org/licenses/by-nc-sa/4.0/

Read the full license:

https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode

Page 3: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 4: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 5: Functional Programming - Lazy Evaluation

Expression Evaluation

reduce an expression to a value

substitution model

take operator with lowest precedence

evaluate its operands (note the recursion)

apply operator to operands

substitute expression with value

evaluating a name: substitute it with its definition

Page 6: Functional Programming - Lazy Evaluation

Expression Evaluation

reduce an expression to a value

substitution model

take operator with lowest precedence

evaluate its operands (note the recursion)

apply operator to operands

substitute expression with value

evaluating a name: substitute it with its definition

Page 7: Functional Programming - Lazy Evaluation

Expression Evaluation Example

(3.14159 * r) * r

--r = 2.4

(3.14159 * 2.4) * r

7.539815999999999 * r

7.539815999999999 * 2.4

18.095558399999998

Page 8: Functional Programming - Lazy Evaluation

Expression Evaluation Example

(3.14159 * r) * r

--r = 2.4

(3.14159 * 2.4) * r

7.539815999999999 * r

7.539815999999999 * 2.4

18.095558399999998

Page 9: Functional Programming - Lazy Evaluation

Expression Evaluation Example

(3.14159 * r) * r

--r = 2.4

(3.14159 * 2.4) * r

7.539815999999999 * r

7.539815999999999 * 2.4

18.095558399999998

Page 10: Functional Programming - Lazy Evaluation

Expression Evaluation Example

(3.14159 * r) * r

--r = 2.4

(3.14159 * 2.4) * r

7.539815999999999 * r

7.539815999999999 * 2.4

18.095558399999998

Page 11: Functional Programming - Lazy Evaluation

Expression Evaluation Example

(3.14159 * r) * r

--r = 2.4

(3.14159 * 2.4) * r

7.539815999999999 * r

7.539815999999999 * 2.4

18.095558399999998

Page 12: Functional Programming - Lazy Evaluation

Function Evaluation

evaluate all actual parameters (left to right)

substitute function application with its definition

substitute formal parameters with actual parameters

Page 13: Functional Programming - Lazy Evaluation

Function Evaluation Example

sqr :: Integer -> Integersqr x = x * x

sumOfSquares :: Integer -> Integer -> IntegersumOfSquares x y = sqr x + sqr y

-- x = 3, y = 2 + 2

Page 14: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 15: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 16: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 17: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 18: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 19: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 20: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 21: Functional Programming - Lazy Evaluation

Function Evaluation Example

sumOfSquares 3 (2 + 2)

sumOfSquares 3 4

sqr 3 + sqr 4

(3 * 3) + sqr 4

9 + sqr 4

9 + (4 * 4)

9 + 16

25

Page 22: Functional Programming - Lazy Evaluation

Evaluation Strategies

strict: evaluate parameters, apply function (“call by value”)

normal order: evaluate parameters when needed (“call by name”)

Church-Rosser propertyresult is the same as long as:

there are no side effects

all evaluations terminate

Page 23: Functional Programming - Lazy Evaluation

Evaluation Strategies

strict: evaluate parameters, apply function (“call by value”)

normal order: evaluate parameters when needed (“call by name”)

Church-Rosser propertyresult is the same as long as:

there are no side effects

all evaluations terminate

Page 24: Functional Programming - Lazy Evaluation

Evaluation Strategies

strict: evaluate parameters, apply function (“call by value”)

normal order: evaluate parameters when needed (“call by name”)

Church-Rosser propertyresult is the same as long as:

there are no side effects

all evaluations terminate

Page 25: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 26: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 27: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 28: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 29: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 30: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 31: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 32: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 33: Functional Programming - Lazy Evaluation

Normal Order Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 34: Functional Programming - Lazy Evaluation

Lazy Evaluation

strict evaluation evaluates parameters only once

but it might evaluate parameters which are not needed

normal order evaluation doesn’t evaluate parameterswhich are not needed

but it might evaluate others more than once

lazy evaluation: evaluate parameter once when first needed

memoization

Page 35: Functional Programming - Lazy Evaluation

Lazy Evaluation

strict evaluation evaluates parameters only once

but it might evaluate parameters which are not needed

normal order evaluation doesn’t evaluate parameterswhich are not needed

but it might evaluate others more than once

lazy evaluation: evaluate parameter once when first needed

memoization

Page 36: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 37: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 38: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 39: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 40: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 41: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 42: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 43: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 44: Functional Programming - Lazy Evaluation

Lazy Evaluation Example

sumOfSquares 3 (2 + 2)

sqr 3 + sqr (2 + 2)

(3 * 3) + sqr (2 + 2)

9 + sqr (2 + 2)

9 + (2 + 2) * (2 + 2)

9 + 4 * 4

9 + 16

25

Page 45: Functional Programming - Lazy Evaluation

Evaluation Strategies

most languages use strict evaluation

Python

def first(x, y):return x

# first(1, 1 // 0) ~> division by zero

Page 46: Functional Programming - Lazy Evaluation

Evaluation Strategies

Haskell uses lazy evaluation by default

Haskell

first :: Integer -> Integer -> Integerfirst x y = x

-- first 1 (1 ‘div‘ 0) ~> 1

Page 47: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 48: Functional Programming - Lazy Evaluation

Short-Circuit Evaluation

short-circuit evaluation:evaluation stops as soon as result is determined

C(a >= 0) && (b < 10)//second clause not evaluated if a < 0

(a >= 0) || (b < 10)//second clause not evaluated if a >= 0

(a >= 0) || (b++ < 10)//dangerous

Page 49: Functional Programming - Lazy Evaluation

Short-Circuit Evaluation

short-circuit evaluation:evaluation stops as soon as result is determined

C(a >= 0) && (b < 10)//second clause not evaluated if a < 0

(a >= 0) || (b < 10)//second clause not evaluated if a >= 0

(a >= 0) || (b++ < 10)//dangerous

Page 50: Functional Programming - Lazy Evaluation

Short-Circuit Evaluation

short-circuit evaluation:evaluation stops as soon as result is determined

C(a >= 0) && (b < 10)//second clause not evaluated if a < 0

(a >= 0) || (b < 10)//second clause not evaluated if a >= 0

(a >= 0) || (b++ < 10)//dangerous

Page 51: Functional Programming - Lazy Evaluation

Short-Circuit Evaluation

code might depend on short-circuit evaluation

Java

// find the index of a key item in a listindex = 0;while ((index < items.length) && (items[index] != key))

index++;

Page 52: Functional Programming - Lazy Evaluation

Short-Circuit Evaluation Examples

and :: Bool -> Bool -> Booland x y = if x then y else False

or :: Bool -> Bool -> Boolor x y = if x then True else y

Page 53: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 54: Functional Programming - Lazy Evaluation

Space Complexity

fac :: Integer -> Integerfac 0 = 1fac n = n * fac (n - 1)

not tail-recursive

creates new stack frames

Page 55: Functional Programming - Lazy Evaluation

Space Complexity Example

facIter :: Integer -> Integer -> IntegerfacIter acc 0 = accfacIter acc n = facIter (acc * n) (n - 1)

tail-recursive

lazy evaluation: doesn’t multiply until the last moment

Page 56: Functional Programming - Lazy Evaluation

Space Complexity Example

facIter 1 n~> facIter (1*n) (n-1)~> facIter ((1*n)*(n-1)) (n-2)~> facIter (((1*n)*(n-1))*(n-2)) (n-3)~> ...

Page 57: Functional Programming - Lazy Evaluation

Space Complexity

possible solution: make the value needed

facIter acc 0 = accfacIter acc n| acc == acc = facIter (acc * n) (n - 1)

Page 58: Functional Programming - Lazy Evaluation

Strictness

force the evaluation of a parameter: seq

seq :: a -> b -> bseq x y| x == x = y -- evaluate x and return y

facIter :: Integer -> Integer -> IntegerfacIter acc 0 = accfacIter acc n = seq acc (facIter (acc * n) (n - 1))

Page 59: Functional Programming - Lazy Evaluation

Strictness

force the evaluation of a parameter: seq

seq :: a -> b -> bseq x y| x == x = y -- evaluate x and return y

facIter :: Integer -> Integer -> IntegerfacIter acc 0 = accfacIter acc n = seq acc (facIter (acc * n) (n - 1))

Page 60: Functional Programming - Lazy Evaluation

Strictness

make a function strict on a parameter: strict

strict :: (a -> b) -> a -> bstrict f x = seq x (f x)

fac :: Integer -> Integerfac n = facIter 1 nwherefacIter :: Integer -> Integer -> IntegerfacIter acc 0 = accfacIter acc n’ = strict facIter (acc * n’) (n’ - 1)

Page 61: Functional Programming - Lazy Evaluation

Strictness

make a function strict on a parameter: strict

strict :: (a -> b) -> a -> bstrict f x = seq x (f x)

fac :: Integer -> Integerfac n = facIter 1 nwherefacIter :: Integer -> Integer -> IntegerfacIter acc 0 = accfacIter acc n’ = strict facIter (acc * n’) (n’ - 1)

Page 62: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 63: Functional Programming - Lazy Evaluation

Infinite Lists

lazy evaluation makes it possible to work withinfinite data structures

create a list with infinite copies of the same element:repeat 42 ~> [42, 42, 42, ...]

repeat :: a -> [a]repeat x = x : repeat x

addFirstTwo :: Num a => [a] -> aaddFirstTwo (x1:x2:_) = x1 + x2

-- addFirstTwo (repeat 42) ~> 84

Page 64: Functional Programming - Lazy Evaluation

Infinite Lists

lazy evaluation makes it possible to work withinfinite data structures

create a list with infinite copies of the same element:repeat 42 ~> [42, 42, 42, ...]

repeat :: a -> [a]repeat x = x : repeat x

addFirstTwo :: Num a => [a] -> aaddFirstTwo (x1:x2:_) = x1 + x2

-- addFirstTwo (repeat 42) ~> 84

Page 65: Functional Programming - Lazy Evaluation

Infinite Ranges

from :: Integer -> [Integer]from n = n : from (n + 1)

-- from 5 -> [5, 6, 7, 8, ...]

-- OR: [5 ..]-- addFirstTwo [7 ..] ~> 15

Page 66: Functional Programming - Lazy Evaluation

Infinite List Example

Fibonacci sequence

fibs :: [Integer]fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

-- take 5 fibs ~> [1, 1, 2, 3, 5]

Page 67: Functional Programming - Lazy Evaluation

Infinite List Example

sieve of Eratosthenes

sieve :: [Integer] -> [Integer]sieve (x:xs) = x : sieve [y | y <- xs, y ‘mod‘ x > 0]

-- sieve [2 ..] -> [2, 3, 5, 7, 11, ...]

primes :: [Integer]primes = sieve [2 ..]

Page 68: Functional Programming - Lazy Evaluation

Infinite List Example

prime number test

isPrime :: Integer -> BoolisPrime n = elemOrd n primes

elemOrd :: Ord a => a -> [a] -> BoolelemOrd n (x:xs)| n < x = False| n == x = True| otherwise = elemOrd n xs

Page 69: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 70: Functional Programming - Lazy Evaluation

Generators

Python uses generators for computing values when needed

yield instead of return

example

def repeat(n):while True:

yield n

answers = repeat(42)for x in answers:

print(x) # 42, 42, 42, ...

Page 71: Functional Programming - Lazy Evaluation

Generators

next call continues from where previous call left off

example

def from_(n):while True:

yield nn += 1

from5 = from_(5)for x in from5:

print(x) # 5, 6, 7, ...

Page 72: Functional Programming - Lazy Evaluation

Generator Example

Fibonacci sequence

def fibs():yield 1yield 1back1, back2 = 1, 1while True:

num = back2 + back1yield numback1 = back2back2 = num

Page 73: Functional Programming - Lazy Evaluation

Topics

1 Expression EvaluationStrategiesShort-Circuit EvaluationSpace Complexity

2 Infinite ListsIntroductionGeneratorsFolding

Page 74: Functional Programming - Lazy Evaluation

Folding

foldr :: (a -> b -> b) -> b -> [a] -> bfoldr f s [] = sfoldr f s (x:xs) = f x (foldr f s xs)

foldl :: (b -> a -> b) -> b -> [a] -> bfoldl f s [] = sfoldl f s (x:xs) = foldl f (f s x) xs

foldr: not tail recursive

foldl: tail recursive

Page 75: Functional Programming - Lazy Evaluation

Folding Example

foldl (*) 1 [1 .. n]~> foldl (*) (1*1) [2 .. n]~> foldl (*) ((1*1)*2) [3 .. n]~> foldl (*) (((1*1)*2)*4) [4 .. n]~> ...

Page 76: Functional Programming - Lazy Evaluation

Folding

foldl’: strict foldl

foldl’ :: (b -> a -> b) -> b -> [a] -> bfoldl’ f s [] = sfoldl’ f s (x:xs) = strict (foldl’ f) (f s x) xs

Page 77: Functional Programming - Lazy Evaluation

Folding Example

foldl’ (*) 1 [1 .. n]~> foldl’ (*) 1 [2 .. n]~> foldl’ (*) 2 [3 .. n]~> foldl’ (*) 6 [4 .. n]~> ...

Page 78: Functional Programming - Lazy Evaluation

Folding Example

foldl (&&) True (repeat False)~> foldl (&&) True [False, False, False, ...]~> foldl (&&) ((&&) True False) [False, False, ...]~> foldl (&&) False [False, False, ...]~> foldl (&&) ((&&) False False) [False, ...]~> foldl (&&) False [False, ...]~> ...-- never terminates

Page 79: Functional Programming - Lazy Evaluation

Folding Example

foldr (&&) True (repeat False)~> foldr (&&) True [False, False, False, ...]~> (&&) False (foldr (&&) True [False, False, ...])~> False

Page 80: Functional Programming - Lazy Evaluation

Folding Example

foldr ((:).(+2)) [] [1 .. n]~> ((:).(+2)) 1 (foldr ((:).(+2)) [] [2 .. n])~> (1+2) : (foldr ((:).(+2)) [] [2 .. n])~> 3 : (foldr ((:).(+2)) [] [2 .. n])~> 3 : ((:).(+2)) 2 (foldr ((:).(+2)) [] [3 .. n])~> 3 : 4 : (foldr ((:).(+2)) [] [3 .. n])~> ...

space complexity: O(1)

Page 81: Functional Programming - Lazy Evaluation

Folding Example

foldr (*) 1 [1 .. n]~> (*) 1 (foldr (*) 1 [2 .. n])~> (*) 1 ((*) 2 (foldr (*) 1 [3 .. n]))~> (*) 1 ((*) 2 ((*) 3 (foldr (*) 1 [4 .. n]))~> ...

space complexity: O(n)

Page 82: Functional Programming - Lazy Evaluation

Folding Strategies

if f is lazy on its second argument, prefer foldr

if the whole list will be traversed, prefer foldl’

Page 83: Functional Programming - Lazy Evaluation

References

Required Reading: ThompsonChapter 17: Lazy programmingChapter 20: Time and space behaviour

20.5: Folding revisited