Tail Recursion Dr. Mattox Beckman University of Illinois at - - PowerPoint PPT Presentation

tail recursion
SMART_READER_LITE
LIVE PREVIEW

Tail Recursion Dr. Mattox Beckman University of Illinois at - - PowerPoint PPT Presentation

Objectives Accumulating Recursion Tail Recursion Dr. Mattox Beckman University of Illinois at Urbana-Champaign Department of Computer Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


slide-1
SLIDE 1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Recursion

  • Dr. Mattox Beckman

University of Illinois at Urbana-Champaign Department of Computer Science

slide-2
SLIDE 2

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Objectives

▶ Understand what makes a function tail recursive. ▶ Explain how the compiler makes tail recursion efficient.

slide-3
SLIDE 3

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Calls

Tail Position A subexpression s of expressions e, if it is evaluated, will be taken as the value of e.

▶ if x > 3 then x + 2 else x - 4 ▶ f (x * 3) — no (proper) tail position here.

Tail Call A function call that occurs in tail position.

▶ if h x then h x else x + g x

slide-4
SLIDE 4

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Your Turn

Find the tail calls!

Example Code

1 calc n i | n==2 = i 2

| odd n = calc (n*3+1) (i+1)

3

| otherwise = calc (n `div` 2) (i+1)

4 5 fib 0 = 0 6 fib 1 = 1 7 fib n = fib (n-1) + fib (n-2)

slide-5
SLIDE 5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

slide-6
SLIDE 6

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 ret

slide-7
SLIDE 7

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 ret y 2 ret

slide-8
SLIDE 8

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 ret y 2 ret z 3 ret

slide-9
SLIDE 9

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 ret y 2 ret z 3 ret 30

slide-10
SLIDE 10

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 ret y 2 30 ret z 3 ret 30

slide-11
SLIDE 11

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 ret y 2 30 ret 30 z 3 ret 30

slide-12
SLIDE 12

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 30 ret y 2 30 ret 30 z 3 ret 30

slide-13
SLIDE 13

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Tail Call Example

▶ If one function calls another in tail position, we get a special

behavior.

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ What happens when we call foo 1?

x 1 30 ret 30 y 2 30 ret 30 z 3 ret 30

slide-14
SLIDE 14

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man...

slide-15
SLIDE 15

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man...

x 1 ret

slide-16
SLIDE 16

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man...

x 1 ret y 2 ret

slide-17
SLIDE 17

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man...

x 1 ret y 2 ret z 3 ret

slide-18
SLIDE 18

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man...

x 1 ret y 2 ret z 3 ret 30

slide-19
SLIDE 19

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man...

x 1 30 ret 30 y 2 ret z 3 ret 30

slide-20
SLIDE 20

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The Tail Call Optimization

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

▶ If that’s the case, we can cut out the middle man... ▶ Actually, we can do even better than that.

slide-21
SLIDE 21

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The optimization

▶ When a function is in tail position, the compiler will recycle the

activation record!

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

slide-22
SLIDE 22

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The optimization

▶ When a function is in tail position, the compiler will recycle the

activation record!

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

x 1 ret

slide-23
SLIDE 23

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The optimization

▶ When a function is in tail position, the compiler will recycle the

activation record!

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

y 2 ret

slide-24
SLIDE 24

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The optimization

▶ When a function is in tail position, the compiler will recycle the

activation record!

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

z 3 ret

slide-25
SLIDE 25

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The optimization

▶ When a function is in tail position, the compiler will recycle the

activation record!

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

z 3 ret 30

slide-26
SLIDE 26

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

The optimization

▶ When a function is in tail position, the compiler will recycle the

activation record!

Example

1 foo x = bar (x+1) 2 bar y = baz (y+1) 3 baz z = z * 10

z 3 ret 30

▶ This allows recursive functions to be written as loops internally.

slide-27
SLIDE 27

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Direct-Style Recursion

▶ In recursion, you split the input into the “first piece” and the “rest of

the input”.

▶ In direct-style recursion: the recursive call computes the result for

the rest of the input, and then the function combines the result with the first piece.

▶ In other words, you wait until the recursive call is done to generate

your result.

Direct Style Summation

1 sum [] = 0 2 sum (x:xs) = x + sum xs

slide-28
SLIDE 28

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Accumulating Recursion

▶ In accumulating recursion: generate an intermediate result now, and

give that to the recursive call.

▶ Usually this requires an auxiliary function.

Tail Recursive Summation

1 sum xx = aux xx 0 2

where aux [] a = a

3

aux (x:xs) a = aux xs (a+x)

slide-29
SLIDE 29

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objectives Accumulating Recursion

Further Reading

▶ Forward recursion can be made to traverse a list at return time

rather than call time, forming a pattern called “There and Back Again,” which can do some interesting things….

▶ Example: write a function convolve which takes two lists

(x1 x2 · · · xn) and (y1 y2 · · · yn) and produces an

  • utput list (x1yn

x2yn−2 · · · xny1) where n is unknown. Use

  • nly O(n) recursive calls, and no temporary lists.

▶ For the solution, see Olivier Danvy’s paper There and Back Again.