-
-
Save james-gardner/5eee98392f81d7ee16d4db5d17cd9cd1 to your computer and use it in GitHub Desktop.
"Thunks, Trampolines, and Continuation Passing" in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* "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