Hacker News new | ask | show | jobs
by e12e 4402 days ago
> you don't need mutable local variables to track the state of the loop.

Erm, that's not really true is it? Isn't the main way which TCO is (usually? always?) done by introducing a counter/accumulator?

It does alleviate the kind of thing you see in c (or other similar languages):

    while(int i = 0; i++; i < 10)
    {
      i--; // whoops
      blah();
    }
But you can hide that counter in many, many (useful) ways, like with iterators, or just some syntax that avoids modifying (or even checking) the counter variable in the loop.

So not having TCO is generally a way to avoid local state variables (but an ever expanding, eventually overflowing stack), implementing TCO tends to re-introduce a counter to avoid growing the stack (and then you have clever ways to emulate stack frames based on how far you got in the loop... sort of giving you the best (and/or worst) of both worlds).

Anyway, if all you want is a safe loop construct, recursion isn't the only option.

(All that said, I like the elegance of "lets pretend the call stack is infinite"-recursion -- and like the idea of TCO. Just don't oversell it.)

1 comments

>> you don't need mutable local variables to track the state of the loop.

> Erm, that's not really true is it? Isn't the main way which TCO is done by introducing a counter/accumulator?

Yes, but accumulators aren't mutable. You're just passing something like acc*n or acc+1 to the tail call... acc is still the same.

Also, accumulators are not analogous to loop counters, they're more like the "sum" variable in this example (also mutable):

   var list = [0,1,2,3];
   var sum = 0;
   for (var i = 0; i < list.length; i++)
     sum += list[i];
> Anyway, if all you want is a safe loop construct, recursion isn't the only option.

I agree! The point of having TCO in a language isn't replacing every for/while loop with recursion. TCO is just an optimization. The right way (at least IMO and IME) is using better abstractions, like you mentioned. Recursion is just a way of easily building those abstractions, as are loops.

Btw, I probably write way more recursive functions in C than I do in Haskell, because in Haskell I have folds and catamorphisms.

I mean, the idiomatic way of summing those numbers as I did above in functional style is probably this:

    [0,1,2,3].reduce(function(a,b){return a+b;}, 0);
Or:

    sum [0,1,2,3]
in haskell ;)