Home CS61A: Higher-Order Functions
Post
Cancel

CS61A: Higher-Order Functions

Higher-Order Functions

  • Allow to design functions with very general methods of computation
  • A function that takes another function as an argument

Generalizing Patterns with Arguments

  • For certain problems, we may find a common structure among the solution and share the implementation across the differing problems.
    • For instance: the value of r^2 is shared by many area formulas (square, circle, polygons, etc)
1
2
3
4
5
6
7
8
9
10
11
12
from math import pi, sqrt

def area_square(r):
    return r*r

def area_circle(r):
    return r * r * pi

def area_hexagon(r):
    return r * r * 3 * sqrt(3) / 2

print(area_hexagon(-10)) # Shapes cannot have negative

Assertion

  • The assert keyword allows us to make assertion statements in python to enforce a certain condition for our code.
    • If the condition is met, nothing happens.
    • If not, an error occurs
1
assert "1" == 1, "String cannot be compared to integers"
1
2
3
4
5
6
7
8
9
---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

Cell In[3], line 1
----> 1 assert "1" == 1, "String cannot be compared to integers"


AssertionError: String cannot be compared to integers
  • Knowing this, we can fix our code from before to account for negative inputs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from math import pi, sqrt

def area_square(r):
    assert r > 0, 'A length must be positive'
    return r*r

def area_circle(r):
    assert r > 0, 'A length must be positive'
    return r * r * pi

def area_hexagon(r):
    assert r > 0, 'A length must be positive'
    return r * r * 3 * sqrt(3) / 2

print(area_hexagon(-10)) # Shapes cannot have negative
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

Cell In[4], line 15
     12     assert r > 0, 'A length must be positive'
     13     return r * r * 3 * sqrt(3) / 2
---> 15 print(area_hexagon(-10)) # Shapes cannot have negative


Cell In[4], line 12, in area_hexagon(r)
     11 def area_hexagon(r):
---> 12     assert r > 0, 'A length must be positive'
     13     return r * r * 3 * sqrt(3) / 2


AssertionError: A length must be positive
  • However, this code is repetitive. Instead, we can generalize the procedure for all three operations.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def area(r, shape_constant):
    assert r > 0, 'A length must be positive'
    return r * r * shape_constant

def area_square(r):
    return area(r, 1)

def area_circle(r):
    return area(r, pi)

def area_hexagon(r):
    return area(r, 3 * sqrt(3) / 2)

print(area_hexagon(10))
print(area_hexagon(-10))
1
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
259.8076211353316



---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

Cell In[7], line 15
     12     return area(r, 3 * sqrt(3) / 2)
     14 print(area_hexagon(10))
---> 15 print(area_hexagon(-10))


Cell In[7], line 12, in area_hexagon(r)
     11 def area_hexagon(r):
---> 12     return area(r, 3 * sqrt(3) / 2)


Cell In[7], line 2, in area(r, shape_constant)
      1 def area(r, shape_constant):
----> 2     assert r > 0, 'A length must be positive'
      3     return r * r * shape_constant


AssertionError: A length must be positive

Generalizing Over Computational Processes

  • Generalization applies over logical and computational processes (actions)
    • Common structures are typically more complex than numbers
    • Ex: Adding consecutive numbers with a certain expression
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def sum_naturals(n):
    """Sum the first N natural numbers
    >>> sum_naturals(5)
    15
    """
    total, k = 0, 1
    while (k <= n):
        total, k = total + k, k + 1
    return total

def sum_cubes(n):
    """Sum the first N cubes of natural numbers
    >>> sum_cubes(5)
    225
    """
    total, k = 0, 1
    while (k <= n):
        total, k = total + k ** 3, k + 1
    return total

sum_cubes(5)
1
225
  • The code above is generally the same with a small difference.
    • We can rewrite this with a higher-order function, by generalizing the process of adding consecutive terms.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def identity(k):
    return k

def cube(k):
    return pow(k, 3)

def summation(n, term):
    """Sum the first N terms of a sequence.
    >>> summation(5, cube)
    225
    """
    total, k = 0, 1
    while (k <= n):
        total, k = total + term(k), k + 1
    return total

summation(5, cube)
1
225

Functions as Return Values

  • Sort of like recursion where we return the output of another function recursively
1
2
3
4
5
6
7
8
9
10
11
12
def make_adder(n):
    """Return a function that takes one argument K and return K + N
    >>> add_three = make_adder(3)
    >>> add_three(4)
    >>> 7
    """
    def adder(k):    # This function is defined within the frame of make_adder, and thus has access to names defined and bound in make_adder
        return k + n # Body of adder
    return adder # Body of make_adder
     
result = make_adder(3)(4)
result
1
7

Locally Defined Functions

  • Functions defined within other function bodies are bound to names in a local frame (of the function that they are defined in)
  • Consider:
1
make_adder(3)(4)
  • We can split this into two parts: the operator and the operand
    • operator: make_adder(3)
    • operand: 4
    • The operator make_adder(3) is like any other operator; it evaluates to a function.
    • The operand is an expression that can evaluate to anything, in this case, 3.

The Purpose of Higher-Order Functions

  • Functions are first-class: Functions can be manipulated as values in Python. They can be passed as argumenst or be returned as return values.
  • Higher-Order Function: A function that takes a function as an argument or returns a function as a return value.
    • Express more general methods of computation
    • Remove repetition from programs
    • Separate concerns among functions. (Each functions have one job)
      • Our functions become much more general -> applicable
    • The functions they take as arguments or return as values may be more specific, from one function to the next
This post is licensed under CC BY 4.0 by the author.

CS61A: Control

CS61A: Lecture 3