Hacker News new | past | comments | ask | show | jobs | submit login
Flambda2 Ep. 2: Loopifying Tail-Recursive Functions (ocamlpro.com)
51 points by todsacerdoti 10 months ago | hide | past | favorite | 7 comments



> [After doing some inlining] we have the ability to loopify the function, but we keep from doing so unless the user specifies the [@@loop] attribute on the function definition.

I don't understand why anyone wouldn't want to convert the recursion to a loop? Surely it's always an improvement.


If you search for @@loop in TFA the last occurrence is in this paragraph:

>if a function is not purely tail-recursive, but contains some tail-recursive calls then the transformation will rewrite those calls but not the other ones. This may result in better code but it's hard to be sure in advance. In such cases (and cases where functions become purely tail-recursive only after inlining), users can force the transformation by using the [@@loop] attribute


Unfortunately this doesn't answer the OP's question. OK, it may not result in better code. But in which cases, and for what reason? EDIT: And for that matter, does "not better" mean "neutral" or "actually worse"? To be clear, this is a flaw in the article, not a criticism of your response to the OP.


One argument I heard some time ago for V8 not implementing TCO is that it results in bad stack traces for debugging.


Conceptually, a tail recursive function represents the body of a loop and we wouldn’t expect a stack trace from a loop either, so this is less of an issue. Am I seeing this incorrectly?


This is correct, however JS/Python pundits expect a stack metaphor when debugging even with an iterative process which can execute in constant space. This leaves us with trampolines as Guido prescribes [1].

[1]: https://neopythonic.blogspot.com/2009/04/final-words-on-tail...


Not really. If a self tail recursive function does not benefit from the optimisation that could be triggered by loopify, the generated code between the tail calls and the loop branch are almost exactly the same (some difference in code layout might happen). OCaml is already very good with that kind of code. This pass is mostly about triggering other optimisations. Another thing is that it is applied before inlining. So if a potential for that where triggered by inlining, we might want to go through the whole process of optimizing that function. This is not something that we do by default since it is quite expensive. Also we often prefer when the performances are somewhat predictable. And inlining is notably not really predictable by default. So if you were to rely on that kind of change to do some magic on your code, maybe it would be a better idea to specify it. (with the @@loop attribute).

This has the obvious problem that you need to know a lot of details about the compiler to get the best performances, but this is the reasoning around that decision for now.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: