Continuation Passing Paradigm#
Initial Set-Up#
from typing import Callable, Any
from functools import partial
def validate_result(expected: int) -> Callable[[int], None]:
def validate_input(actual: int) -> None:
assert actual == expected, actual
return validate_input
def loop(
function: Callable[[int, Callable[[int], None]], None],
n: int,
continuation: Callable[[int], None],
*args: int
) -> None:
if n <= 0:
continuation(*args)
return
aux = partial(function, continuation=continuation)
for _ in range(n - 1):
aux = partial(function, continuation=aux)
aux(*args)
Predecessor and Successor#
def predecessor(a: int, continuation: Callable[[int], Any]) -> None:
continuation(a - 1)
predecessor(1, validate_result(0))
predecessor(10, validate_result(9))
def successor(a: int, continuation: Callable[[int], Any]) -> None:
continuation(a + 1)
successor(0, validate_result(1))
successor(10, validate_result(11))
Addition#
def addition(addend_1: int, addend_2: int, continuation: Callable[[int], Any]) -> None:
loop(successor, addend_2, continuation, addend_1)
addition(0, 0, validate_result(0))
addition(1, 0, validate_result(1))
addition(0, 1, validate_result(1))
addition(10, 10, validate_result(20))
Multiplication#
def multiplication(
multiplicand: int, multiplier: int, continuation: Callable[[int], Any]
) -> None:
if multiplicand == 0 or multiplier == 0:
continuation(0)
return
fixed_addition = partial(addition, addend_2=multiplicand)
loop(fixed_addition, multiplier, continuation, 0)
multiplication(0, 0, validate_result(0))
multiplication(2, 0, validate_result(0))
multiplication(0, 2, validate_result(0))
multiplication(10, 10, validate_result(100))
Exponentiation#
def exponentiation(
base: int, exponent: int, continuation: Callable[[int], Any]
) -> None:
fixed_multiplication = partial(multiplication, multiplier=base)
loop(fixed_multiplication, exponent, continuation, 1)
exponentiation(1, 0, validate_result(1))
exponentiation(0, 1, validate_result(0))
exponentiation(3, 3, validate_result(27))