4.12.1.4–4.12.1.5 - Partial application and function composition (Python)

4.12.1.4–4.12.1.5 - Partial application and function composition (Python)

Read curried function types, work out what remains after partial application, and combine functions in the correct order. Explore returned functions in Python while keeping the functional notation needed for written Paper 2 responses.

One-, two- and three-argument types

A curried function receives one argument at a time, returning another function whenever more arguments remain.

The uncurried addition type integer×integer→integer\mathrm{integer}\times\mathrm{integer}\to\mathrm{integer} maps a pair to an integer. A curried version has the type

add⁡:integer→(integer→integer).\operatorname{add}:\mathrm{integer}\to(\mathrm{integer}\to\mathrm{integer}).

After receiving the first integer, add returns a function of type integer → integer. That returned function accepts the second integer and produces the sum. For example, add 4 denotes an add-four function; add 4 7 evaluates to 11.

When brackets are omitted, type arrows associate to the right: A→B→CA\to B\to C means A→(B→C)A\to(B\to C). Function application associates to the left: add 4 7 means (add 4) 7. These are complementary conventions, not contradictory ones: first obtain a function, then apply it.

Curried functionComplete typeAfter one supplied integerAfter two supplied integers
square x = x*xinteger → integerInteger resultNot applicable
add x y = x+yinteger → integer → integerFunction: integer → integerInteger result
cost price count fee = price*count+feeinteger → integer → integer → integerFunction: integer → integer → integerFunction: integer → integer

A one-argument function such as square is fully applied after its one required argument. Supplying no argument merely refers to that function. For a two- or three-argument function, supplying fewer than all required arguments can create a useful new function; the final argument completes the calculation.

For cost 3 4, price and count are fixed. The remaining fee is still variable, so the result is a function taking a fee and returning 12+fee12+\mathrm{fee}. It is not yet the integer 12.

Partial application and returned functions

Partial application fixes some arguments now and returns a function that can receive the remaining arguments later.

Partial function application

Applying fewer than all required arguments of a function, producing a new function with those arguments fixed.

Python does not automatically turn every two-parameter definition into a curried function: calling a normal def add(a, b) with only a raises an error unless its interface allows it. Nested function definitions make the curried stages explicit. A returned inner function retains access to the outer call's fixed values; this is a closure.

Keep a partially applied function

{"code":"def add(first):\n def with_second(second):\n return first + second\n return with_second\n\nadd_four = add(4)\nprint(add_four(7))\nprint(add_four(-2))\nprint(add(1)(9))\n","instructions":"Predict all three integers, then run. Distinguish add(4), which returns a function, from add(4)(7), which returns an integer. Change the fixed argument in add_four = add(4) to 9, rename the variable add_nine throughout, then predict and run again. The final independent add(1)(9) call should remain unchanged.","files":[],"original_filename":"main.py","runtime_profile":"python-console-v1","file_mode":"fresh"}

Two calls such as add(4) and add(9) return distinct functions retaining different fixed values. Neither overwrites a global first argument. The same idea extends to three stages: each function returns the next stage until the final result is available.

Continue this lesson.

You’re previewing NovaLearn without an account. Create a free account to read the rest.

Create free account