function Async() { return { bind: bind, parallel: parallel, run: run, sequence: sequence, wait: wait, wrap: wrap }; function bind(m, f) { return function(g) { m(function(x) { f(x)(g); }); } } function parallel() { var threads = arguments; var pending = threads.length; var results = []; return function(f) { var useResult = function(i) { return function(x) { results[i] = x; pending--; if(pending < 1) { f(results); } }; }; for(var i = 0; i < threads.length; i++) { threads[i](useResult(i)); } }; } function run() { var m; if(arguments.length == 1) { m = arguments[0]; } else { m = sequence.apply(null, arguments); } m(function() {}); } function sequence() { var steps = arguments; var i = 0; return function(f) { var step = function() { if(i < steps.length) { steps[i++](step); } else { f(); } } step(); }; } function wait(delay) { return function(f) { setTimeout(f, delay); }; } function wrap(x) { return function(f) { f(x); }; } }