22
In functional programming, it is very common to use functions recursive. Certain languages, such as Scheme, do not even have control structures for loops, depending on recursion to iterate over lists.
Javascript has functional features, such as first-class functions, but has restrictions on the use of recursion. For example:
function fatorial(num) {
if (num === 0) {
return 1;
}
return num * fatorial(num - 1);
}
fatorial(5); // 120
fatorial(100000); // RangeError: Maximum call stack size exceeded
Please ignore the fact that fatorial(100000)
is a number that Javascript is not even able to represent.
If the number of recursions exceeds a certain limit, the engine is not able to process the result by launching an error or locking the program. This is because the size of the call stack (which stores the execution context of each function invocation - which includes local variables and the reference to the "parent" scope of the function, basis of the mechanism of the closures) has a fixed size. And this limit exists to ensure that the call stack does not consume excess memory.
However, there is a technique to avoid this limitation, depending on how the function code is structured. If the recursive call is in position "tail", that is, it is the last instruction of the function, its execution context is dispensable, as it is guaranteed that the function will not need it anymore when recursive calls are popped. Thus, it is possible to clean or "recycle" the frame (frame) of the stack used by the execution context of the running function, and use it for the recursive call, so that a tail recursive function ends up using a single stack frame for the entire operation. This technique is known as tail call optimization (Tail call Optimization).
Question
Although this technique is widely known, no Javascript engine seems to use it, either in the interpreter itself or as part of the operations performed by the JIT compilers that all modern Engines use. The question is, why? Is there any restriction in language that makes this optimization impossible? Or maybe it’s possible, but too costly?
The grammar of the next version of the language (Ecmascript 6, still in draft) includes checks for the tail position, predicting this type of optimization. However, I do not think that the lack of this in the current version would prevent the technique from being used today.
bfavaretto was also bitten by the literal translation mosquito :)
– Maniero
I almost created a "tail-recursion-optimization" tag, but it exceeds the maximum allowed 25 characters :)
– bfavaretto
Recursion in "syrup"... made me want to eat a dessert ;)
– utluiz
Wow, "tail recursion" is a commonly used term, not a literal translation. Even if it were "tail recursion"...
– mgibsonbr
But also calculating 100000! is awesome. In no situation will you need it. To get an idea the result is 2.8242294079603478293421578024535517749492 10 456573.
– user622
@Gabrielsantos It was just an example! Note that I myself said, in fine print, that the result is not even representable as Number em js. The fact is that these stack overflow errors occur when using recursion intensively, which is common in functional programming.
– bfavaretto
6 years later and to this day have not implemented this in Javascript. It seems that will stay in the role of Ecmascript forever... Unfortunate.
– Luiz Felipe