We can use higher-order functions to convert a function that takes multiple arguments into a chain of functions that each take a single argument. More specifically, given a function f(x, y), we can define a function g such that g(x)(y) is equivalent to f(x, y). Here, g is a higher-order function that takes in a single argument x and returns another function that takes in a single argument y. This transformation is called currying.
As an example, we can define a curried version of the pow function:
>>> def curried_pow(x):def h(y):return pow(x, y)return h>>> curried_pow(2)(3)8
Some programming languages, such as Haskell, only allow functions that take a single argument, so the programmer must curry all multi-argument procedures. In more general languages such as Python, currying is useful when we require a function that takes in only a single argument. For example, the map pattern applies a single-argument function to a sequence of values. In later chapters, we will see more general examples of the map pattern, but for now, we can implement the pattern in a function:
>>> def map_to_range(start, end, f):while start < end:print(f(start))start = start + 1
We can use map_to_range and curried_pow to compute the first ten powers of two, rather than specifically writing a function to do so:
>>> map_to_range(0, 10, curried_pow(2))1248163264128256512
We can similarly use the same two functions to compute powers of other numbers. Currying allows us to do so without writing a specific function for each number whose powers we wish to compute.
In the above examples, we manually performed the currying transformation on the pow function to obtain curried_pow. Instead, we can define functions to automate currying, as well as the inverse uncurrying transformation:
>>> def curry2(f):"""Return a curried version of the given two-argument function."""def g(x):def h(y):return f(x, y)return hreturn g>>> def uncurry2(g):"""Return a two-argument version of the given curried function."""def f(x, y):return g(x)(y)return f>>> pow_curried = curry2(pow)>>> pow_curried(2)(5)32>>> map_to_range(0, 10, pow_curried(2))1248163264128256512
The curry2 function takes in a two-argument function f and returns a single-argument function g. When g is applied to an argument x, it returns a single-argument function h. When h is applied to y, it calls f(x, y). Thus, curry2(f)(x)(y) is equivalent to f(x, y). The uncurry2 function reverses the currying transformation, so that uncurry2(curry2(f)) is equivalent to f.
>>> uncurry2(pow_curried)(2, 5)32
