Continuation passing style
This sophisticated technique of arranging recursion allows you to avoid stack consumption by putting all function calls into the tail position with continuation, that is, a function that performs the remaining computations instead of returning result to the caller. Let me demonstrate this technique by refactoring the factorial implementation one more time as shown in the following snippet (Ch7_6.fsx
):
let rec ``factorial (cps)`` cont = function | z when z = 0I -> cont 1I | n -> ``factorial (cps)`` (fun x -> cont(n * x)) (n - 1I)
Although slightly mind-bending, the code consists of all tail calls:
A recursive call to itself
``factorial (cps)``
is a tail callA new continuation anonymous function also makes a tail call to the old continuation,
cont
The cont
function has inferred signature of (BigInteger -> 'a);
so, in order to perform the sought-for calculations, using the id
identity function for the cont
as the first argument of ``factorial (cps...