Created
June 23, 2012 04:21
-
-
Save jneen/2976833 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
var P = require('pjs').P; | |
var util = require('util'); | |
var stack = function() { | |
return (new Error).stack.split(/\s+at\s+/).slice(1); | |
} | |
var slice = [].slice; | |
var Thunk = P(function(thunk) { | |
thunk.toString = function() { | |
return '[Thunk '+util.inspect(this.fn)+' '+util.inspect(this.args)+']'; | |
} | |
thunk.init = function(fn, args) { | |
this.fn = fn; | |
this.args = slice.call(args); | |
}; | |
thunk.call = function() { | |
return this.fn.apply(null, this.args); | |
} | |
thunk.trampoline = function() { | |
var thunk = this; | |
for (;;) { | |
console.log('bounce', thunk); | |
if (thunk instanceof Thunk) { | |
thunk = thunk.call(); | |
} | |
else { | |
return thunk; | |
} | |
} | |
} | |
}); | |
function id(x) { return x; } | |
function makeTrampoline(def) { | |
function recurse() { return Thunk(thunkfn, arguments); } | |
var thunkfn = def(recurse); | |
return function() { | |
var args = slice.call(arguments); | |
return Thunk(thunkfn, [id].concat(args)).trampoline(); | |
} | |
} | |
var gcd = exports.gcd = makeTrampoline(function(recurse) { | |
return function(cc, a, b) { | |
// prevent infinite loop on NaN | |
if (isNaN(a) || isNaN(b)) return cc(NaN); | |
if (a === 0 || b === 0) return cc(1.0/0); | |
// ensure a < b | |
if (a > b) { | |
var tmp = a; | |
a = b; b = tmp; | |
} | |
var mod = b % a; | |
// if a divides b, the gcd is a | |
if (mod === 0) return cc(a); | |
// otherwise recurse with Euclid's algorithm | |
return recurse(cc, mod, a); | |
} | |
}); | |
var factorial = exports.factorial = makeTrampoline(function(recurse) { | |
function multiplier(cc, n) { | |
return function(m) { return cc(m * n); }; | |
} | |
return function(cc, n) { | |
if (n <= 1) return cc(1); | |
return recurse(multiplier(cc, n), n - 1); | |
}; | |
}); | |
console.log(factorial(6)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment