Skip to content

Instantly share code, notes, and snippets.

@buzzdecafe
Forked from AutoSponge/tco.md
Last active December 15, 2015 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save buzzdecafe/5297203 to your computer and use it in GitHub Desktop.
Save buzzdecafe/5297203 to your computer and use it in GitHub Desktop.
function recur(fn) {
return function () {
var bounce = fn.apply(this, arguments);
while (bounce.onTheTrampoline) {
bounce = bounce();
}
return bounce;
};
}
var sum1 = recur(function sum(x, y) {
function z() {
return y > 0 ? sum(x + 1, y - 1) :
y < 0 ? sum(x - 1, y + 1) :
x;
};
z.onTheTrampoline = true;
return z;
});
function trampoline(bounce) {
while(bounce.bouncy) {
bounce = bounce();
}
return bounce;
}
function mkBouncy(fn) {
fn.bouncy = true;
return fn;
}
function upTo(n) {
function inner(i) {
return (i === n) ? n : mkBouncy(function() { return inner(i + 1); });
}
return trampoline(inner(0));
}
upTo(1000000);
function trampoline(bounce) {
while(typeof bounce === "function") {
bounce = bounce();
}
return bounce;
}
function upTo(n) {
function inner(i) {
return (i === n) ? n : function() { return inner(i + 1); };
}
return trampoline(inner(0));
}
upTo(1000000);
function getInstance(self, constructor) {
return self instanceof constructor ? self : new constructor;
}
function done(result) {
var self = getInstance(this, done);
self.isDone = true;
self.result = result;
return self;
}
function cont(thunk) {
var self = getInstance(this, cont);
self.isDone = false;
self.thunk = thunk;
return self;
}
function trampoline(bounce) {
while(!bounce.isDone) {
bounce = bounce.thunk();
}
return bounce.result;
}
function recurse(n) {
function inner(i) {
//if (i > 20790) console.log(i);
if (i === n) {
return done(n);
}
return cont(function() {
return inner(i + 1);
});
}
return trampoline(inner(0));
}
recurse(20800);
/* fails to reach a point where it can console results */
function recurse(i) {
if (i > 20799) console.log(i);
return i < 20800 ? recurse(i + 1) : 20800;
}
recurse(0);
function trampoline(bounce) {
while(bounce.thunk) {
bounce = bounce.thunk();
}
return bounce.result;
}
function recurse(n) {
function inner(i) {
if (i === n) {
return {
result: n
};
}
return {
thunk: function() {
return inner(i + 1);
}
};
}
return trampoline(inner(0));
}
recurse(20800);
//this version more clearly demonstrates the technique.
//this version probably also outperforms the other, jsperf incoming
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment