Note: attended the evening lecture on Thu, Sep 12

Taking a multi-argument function and converting it into a single-argument higher-order function.

For example, a function with two arguments:

```
def curry2(h):
def f(x):
def g(y):
return h(x, y)
return g
return f
```

Applying this to the `add`

function:

```
def make_adder(n):
"""
>>> make_adder(2)(3)
5
>>> add(2, 3)
5
"""
return lambda k: n + k
```

Using lambda functions:

`curry2 = lambda h: lambda x: lambda y: h(x, y)`

In a large program, if you know one argument early but not the others until later, you can use currying to get the process started and execute the function when you've got all of the arguments, filling them in one by one.

To see how you get from the input to the output, you could `trace`

the function in question:

```
def trace(f):
def traced(x):
print('calling', f.__name__, 'on', x)
return f(x)
return traced
def square(x):
return x * x
square = trace(square)
def sum_squares_up_to(n):
total = 0
while n > 0:
total, n = total + square(n), n - 1
return total
```

This is built into Python:

```
@trace
def square(x):
return x * x
```