Skip to content

Instantly share code, notes, and snippets.

@james-gardner
Forked from trdarr/cps.js
Created June 2, 2017 13:36
Show Gist options
  • Save james-gardner/5eee98392f81d7ee16d4db5d17cd9cd1 to your computer and use it in GitHub Desktop.
Save james-gardner/5eee98392f81d7ee16d4db5d17cd9cd1 to your computer and use it in GitHub Desktop.
"Thunks, Trampolines, and Continuation Passing" in JavaScript
/* "Thunks, Trampolines, and Continuation Passing"
* Python implementation from http://jtauber.com/blog/2008/03/30/
* JavaScript implementation by Thomas Darr <[email protected]>.
*/
// thunk = lambda name: lambda *args: lambda: name(*args)
var thunk = function thunk(fn) {
return function _thunk() {
var splat = Array.prototype.slice.apply(arguments);
return function __thunk() { return fn.apply(this, splat); };
};
};
/* def _trampoline(bouncer):
* while callable(bouncer):
* bouncer = bouncer()
* return bouncer
*
* trampoline = lambda f: lambda *args: _trampoline(f(*args))
*/
var trampoline = function trampoline(fn) {
return function _trampoline() {
var splat = Array.prototype.slice.apply(arguments);
return (function __trampoline(bouncer) {
while (typeof bouncer === 'function')
bouncer = bouncer.apply();
return bouncer;
})(fn.apply(this, splat));
};
};
var factorial = function factorial(n) {
/* _factorial = (lambda n, c=identity: c(1) if n == 0
* else thunk(_factorial)(n - 1, lambda result: thunk(c)(n * result)))
*
* factorial = trampoline(_factorial)
*/
return trampoline(function _factorial(n, continuation) {
// identity = lambda x: x
continuation = continuation || function identity(x) { return x; };
if (n < 2) return continuation(1);
else return thunk(_factorial)(n - 1, function(result) {
return thunk(continuation)(n * result);
});
})(n);
};
var fibonacci = function fibonacci(n) {
return trampoline(function _fibonacci(n, continuation) {
continuation = continuation || function identity(x) { return x; };
if (n < 2) return continuation(1);
else return thunk(_fibonacci)(n - 1, function(one) {
return thunk(_fibonacci)(n - 2, function(two) {
return thunk(continuation)(one + two);
});
});
})(n);
};
var sum = function sum(n) {
return trampoline(function _sum(n, continuation) {
continuation = continuation || function identity(x) { return x; };
if (n < 1) return continuation(n);
else return thunk(_sum)(n - 1, function(result) {
return thunk(continuation)(n + result);
});
})(n);
};
console.log(24 === factorial(5));
console.log(89 === fibonacci(10));
console.log(55 === sum(10));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment