Anonymous recursion in the continuation-pass style can be performed as follows (using JS6 as a language):
// CPS wrappers const dec = (n, callback)=>{ callback(n - 1) } const mul = (a, b, callback)=>{ callback(a * b) } const if_equal = (a, b, then, else_)=>{ (a == b ? then : else_)() } // Factorial const F = (rec, n, a, callback)=>{ if_equal(n, 0, ()=>{callback(a)}, ()=>{dec(n, (rn)=>{ mul(a, n, (ra)=>{ rec(rec, rn, ra, callback) }) }) }) } const fact = (n, callback)=>{ F(F, n, 1, callback) } // Demo fact(5, console.log)
To get rid of the double use of the label F , we can use the utility function as follows:
const rec3 = (f, a, b, c)=>{ f(f, a, b, c) } const fact = (n, callback)=>{ rec3(F, n, 1, callback) }
This allows us to embed F :
const fact = (n, callback)=>{ rec3((rec, n, a, callback)=>{ if_equal(n, 0, ()=>{callback(a)}, ()=>{dec(n, (rn)=>{ mul(a, n, (ra)=>{ rec(rec, rn, ra, callback) }) }) }) }, n, 1, callback) }
We can go to inline rec3 to make the fact self-preserving:
const fact = (n, callback)=>{ ((f, a, b, c)=>{ f(f, a, b, c) })((rec, n, a, callback)=>{ if_equal(n, 0, ()=>{callback(a)}, ()=>{dec(n, (rn)=>{ mul(a, n, (ra)=>{ rec(rec, rn, ra, callback) }) }) }) }, n, 1, callback) }
The following JavaScript uses the same approach to implement the for loop.
const for_ = (start, end, func, callback)=>{ ((rec, n, end, func, callback)=>{ rec(rec, n, end, func, callback) })((rec, n, end, func, callback)=>{ func(n, ()=>{ if_equal(n, end, callback, ()=>{ S(n, (sn)=>{ rec(rec, sn, end, func, callback) }) }) }) }, start, end, func, callback) }
This is the fully async part of FizzBuzz I made by https://gist.github.com/Recmo/1a02121d39ee337fb81fc18e735a0d9e