# Higher-Order Functions - Wed, Sep 4

## Iteration Example: The Fibonacci Sequence

``````def fib(n):
"""Compute the nth Fibonacci number, for N >= 1."""
pred, curr = 0, 1
k = 1
while k < n:
pred, curr = curr, pred + curr
k = k + 1
return curr``````

## Designing Functions

• A function's domain is the set of all inputs it might possibly take as arguments.
• A function's range is the set of all output values it might possibly return.
• A pure function's behavior is the relationship it creates between input and output.

## A Guide to Designing Functions

• Give each function exactly one job, but make it apply to many related situations
``````>>> round(1.23)
1
>>> round(1.23, 1)
1.2
>>> round(1.23, 0)
1
>>> round(1.23, 5)
1.23``````
• Don't repeat yourself (DRY): Implement a process just once, but execute it many times

## Generalization

Regular geometric shapes relate length and area

``````from math import pi, sqrt

def area(r, shape_constant):
assert r > 0, 'r 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)``````

## Generalizing Over Computational Processes

The common structure among functions may be a computational process, rather than a number.

``````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
``````def sum_cubes(n):
"""Sum the first N cubes.

>>> sum_naturals(5)
225
"""
total, k = 0, 1
while k <= n:
total, k = total + pow(k, 3), k + 1

To generalize these two functions:

``````def identity(k):
return k

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

def summation(n, term):
"""Sum the first N TERMs in a sequence.

>>> summation(5, cube)
225
>>> summation(5, identity)
15
"""
total, k = 0, 1
while k <= n:
total, k = total + term(k), k + 1
``````def make_adder(n):