Basically you rewrite your recursive functions so that instead of calling another function they return a parameterless closure. Then you can iteratively call your first function, and the function it returns, and the function it returns etc until the return value is not a function.
It's like with lazy evaluation. It allows you to write novel kinds of algorithms and data structures, and you can emulate it with helper objects or structures, but it's tedious, muddles the essence of the code, and the implementation without them (the helper structures) would be simpler if the language provided you with lazy expressions.
In other words, repeat with me: loops don't compose. They're not first-class, they're not extensible, they're a syntactic construct.
Iterators do, though. Most of the languages that don't do TCO instead lean on those instead: C++, C#, Python, and eventually JavaScript.
function fact(x) {
return (function factIter(i, total){
if(i<=1){ return total; }
return factIter(i-1, total*i);
})(x,1);
}
However, if you're willing to allow mutation in non-accessible code or closures, there are options: function fact(x) {
if(i<=1) { return 1; }
return _.range(1,x+1).reduce(
function(sum, x) { return sum*x; }
);
}There are lots of concepts that are still applicable even when using imperative loops.
I realize that JS is becoming more popular for various tasks -- not always relating to the web -- but still, I kind of doubt that 99% of the JS out there is going to run up against these types of problems. Perhaps something like Uglify.js or similar might, but then again, if you're implementing a parser (or any other static code analyzer/tool) then you're probably going to avoid most libs to start with.
Pulling apart the iteration over a collection of elements and behavior performed to each element is one of those insights that a functional style is good at communicating, and leads to better more testable code.
function each(arr,fn,pos) {
pos = pos || 0;
fn(arr[pos++])
if(pos < arr.length)
each(arr,fn,pos);
}
Seems like a recipe for a disaster.right now i need to build my own stack, and "unstack" it manually.