1 of 39

Higher Order Functions

Thursday, 6/25

2 of 39

Announcements

  • Fill out OK Issues survey
  • Tutoring
    • Signups available today
    • Starts this Saturday
    • Tutoring sessions next week (up to Friday) will review week 1 material
  • Homework 1 due Friday, June 26
  • Homework 2 due Monday, June 29
  • Project 1: Hog will be released this afternoon
    • Due next Thursday, July 2
    • Work with at most 1 partner
      • Must declare partner on ok!
    • Start early!

3 of 39

Higher Order Functions

  1. Review: functions as arguments
  2. Nested functions
  3. Functions as return values
  4. Lambda functions

4 of 39

Review: Functions as Arguments

def summation(term, n):

i, total = 1, 0

while i <= n:

total += term(i)

i += 1

return total

>>> def double(x):

... return 2*x

...

>>> summation(double, 3)

12

1-argument�function

5 of 39

Higher Order Functions

  • Review: functions as arguments
  • Nested functions
  • Functions as return values
  • Lambda functions

6 of 39

Nested functions

Functions can be defined inside functions.

This is useful for helper functions.

def f(a, b, c):� numer_ab = a*b + b/a + a**b� denom_ac = a*c + c/a + a**c� return numer_ab / denom_ac

numer_ab & denom_ac are very similar!

7 of 39

Nested functions

Helper functions can simplify code!

def f(a, b, c):� def g(d):� return a*d + d/a + a**d� return g(b) / g(c)��f(2, 3, 4)

g is defined inside the body of f!

8 of 39

Nested functions

Helper functions can simplify code!

def f(2, b, c):� def g(d):� return a*d + d/a + a**d� return g(b) / g(c)��f(2, 3, 4)

9 of 39

Nested functions

Helper functions can simplify code!

def f(2, b, c):� def g(d):� return 2*d + d/2 + 2**d� return g(b) / g(c)��f(2, 3, 4)

10 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, c):� def g(d):� return 2*d + d/2 + 2**d� return g(3) / g(4)��f(2, 3, 4)

11 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, c):� def g(3):� return 2*d + d/2 + 2**d� return g(3) / g(4)��f(2, 3, 4)

12 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, c):� def g(3):� return 2*3 + 3/2 + 2**3� return g(3) / g(4)��f(2, 3, 4)

13 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, c):� def g(3):� return 2*3 + 3/2 + 2**3� return 15.5 / g(4)��f(2, 3, 4)

14 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, 4):� def g(4):� return 2*4 + 4/2 + 2**4� return 15.5 / g(4)��f(2, 3, 4)

15 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, 4):� def g(4):� return 2*4 + 4/2 + 2**4� return 15.5 / 26.0��f(2, 3, 4)

16 of 39

Nested functions

Helper functions can simplify code!

def f(2, 3, 4):� def g(4):� return 2*4 + 4/2 + 2**4� return 15.5 / 26.0��1.6774193548387097

17 of 39

Higher Order Functions

  • Review: functions as arguments
  • Nested functions
  • Functions as return values
  • Lambda functions

18 of 39

Adders

Functions that add some number to another number

def add_1(x):� return x + 1

def add_2(x):� return x + 2

def add_3(x):� return x + 3

...

def add_128(x):� return x + 128

(Demo)

19 of 39

make_adder

def make_adder(n):� """Return func that takes one arg k and returns k + n�� >>> add_three = make_adder(3)� >>> add_three(4)7� """� def adder(k):� return k + n� return adder

function that returns a function

nested function

name add_three is bound to a function

can refer to names in enclosing functions

20 of 39

make_adder

make_adder

( 4 )

( 3 )

def make_adder(n): def adder(k):� return k + n� return adder

For compound call expressions, read left to right

<func make_adder>

3

<func adder>

21 of 39

make_adder

( 4 )

def make_adder(n): def adder(k):� return k + nreturn adder

For compound call expressions, read left to right

7

<func adder>

22 of 39

Environment diagram: make_adder

def make_adder(n): def adder(k):� return k + n� return adder

make_adder(3)(4)

Label function with its parent frame

Parent frame: frame in which the function is defined

23 of 39

Environment diagram: make_adder

def make_adder(n): def adder(k):� return k + n� return adder

make_adder(3)(4)

Label function with its parent frame

Copy parent frame from label on function object

Label frame with a unique identifier

24 of 39

Environment diagram: make_adder

def make_adder(n): def adder(k):� return k + n� return adder

make_adder(3)(4)

Parent frame is f1!

25 of 39

Environment diagram: make_adder

def make_adder(n): def adder(k):� return k + n� return adder

make_adder(3)(4)

26 of 39

Environment diagram: make_adder

def make_adder(n): def adder(k):� return k + n� return adder

make_adder(3)(4)

27 of 39

Environment diagram: make_adder

def make_adder(n): def adder(k):� return k + n� return adder

make_adder(3)(4)

To lookup value of n, follow the parent frames.

n?

28 of 39

Higher Order Functions

  • Review: functions as arguments
  • Nested functions
  • Functions as return values
  • Lambda functions

29 of 39

make_adder

def make_adder(n): def adder(k):� return k + n� return adder

Why bother naming adder if we only use the name once?

30 of 39

Lambda functions

def make_adder(n):� return lambda k: n + k

The lambda expression creates an anonymous function!

lambda <parameters>: <return expression>

31 of 39

Translating between named and anonymous functions

def square(x):� return x * x

square = lambda x: x * x

No “return”!

32 of 39

Translating between named and anonymous functions

def make_adder(n):� return lambda k: n + k

make_adder = lambda n: lambda k: n + k

33 of 39

Translating between named and anonymous functions

def make_adder(n):� return lambda k: n + k

def make_adder(n):� def adder(k):� return n + kreturn adder

make_adder = lambda n: lambda k: n + k

34 of 39

Lambda functions

Lambdas are expressions! You can use them anywhere you can use any other expression.

A lambda’s body can only be a single expression. This is the return expression.

Use sparingly! Better to have clear names.

35 of 39

Environment diagram: lambdas

id_func = lambda x: x

id_func(0)

36 of 39

Environment diagram: make_adder

def make_adder(n):� return lambda k: n + k

add_3 = make_adder(3)

add_3(4)

37 of 39

Lambda functions: practice

>>> def summation(term, n):

... i, total = 1, 0

... while i <= n:

... total += term(i)

... i += 1

... return total

...

>>> summation(lambda x: x**2, 3)

14

38 of 39

Lambda functions: practice

def repeat(f, x):� while f(x) != x:� x = f(x)� return x

def g(y):� return (y + 5) // 3

result = repeat(g, 5)

39 of 39

Hog demo!