function sum (fn, xs) { var toRet = 0; for (var i = 0, ii = xs.length; i < ii; i++) { toRet += fn(xs[i], i, xs); } return toRet; } function update(t, o) { for (var k in o) { t[k] = o[k]; } return t; } function depGraph(graph) { var deps = {}; for (var k in statsGraph) { var fnStr = graph[k].toString(); var fnArgs = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).split(/\s*,\s*/); deps[k] = fnArgs; } return deps; } function satisfyDeps(depsList, results) { var acc = []; for (var i = 0, ii = depsList.length; i < ii; i++) { if (typeof results[depsList[i]] == 'undefined') { return false; } else { acc.push(results[depsList[i]]); } } return acc; } function eagerCompile(graph) { return function(startValue) { var deps = depGraph(graph); var k = Object.keys(deps); var res = update({}, startValue); var processing, args, missingDep = true; do { processing = false; for (var i = 0, ii = k.length; i < ii; i++) { if (typeof res[k[i]] == 'undefined') { if (args = satisfyDeps(deps[k[i]], res)) { res[k[i]] = graph[k[i]].apply(res, args); processed = true; missingDep = false } } } if (missingDep) { throw 'Missing dependency'; } } while (processing); return res; } } var statsGraph = { n: function(xs) { return xs.length; }, m: function(xs, n) { return sum(function(x){ return x; }, xs) / n; }, m2: function(xs, n) { return sum(function(x){ return x * x; }, xs) / n; }, v: function(m, m2) { return m2 - (m * m); } }; var stats = eagerCompile(statsGraph); console.log(stats({xs: [1, 2, 3, 6]}));