OCaml function calls consume space on the system stack. Operating systems set default limits on the stack space which are much lower than the available memory. If a program runs out of stack space, they get the dreaded "Stack Overflow" exception -- they crash. As a result, OCaml programmers have to be careful, when they write recursive functions, to remain in the so-called _tail-recursive_ fragment, using _tail_ calls that do not consume stack space. This discipline is a source of difficulties for both beginners and experts. Beginners have to be taught recursion, and then tail-recursion. Experts disagree on the "right" way to write `List.map`. The direct version is beautiful but not tail-recursive, so it crashes on larger inputs. The naive tail-recursive transformation is (slightly) slower than the direct version, and experts may want to avoid that cost. Some libraries propose horrible implementations, unrolling code by hand, to compensate for this performance loss. In general, tail-recursion requires the programmer to manually perform sophisticated program transformations. In this work we propose an implementation of "Tail Modulo Cons" (TMC) for OCaml. TMC is a program transformation for a fragment of non-tail-recursive functions, that rewrites them in _destination-passing style_. The supported fragment is smaller than other approaches such as continuation-passing-style, but the performance of the transformed code is on par with the direct, non-tail-recursive version. Many useful functions that traverse a recursive datastructure and rebuild another recursive structure are in the TMC fragment, in particular `List.map` (and `List.filter`, `List.append`, etc.). Finally those functions can be written in a way that is beautiful, correct on all inputs, and efficient.
翻译:OCaml 函数调用系统堆叠中的空间。 操作系统对堆叠空间设定了比可用存储空间要低得多的默认限制。 如果程序运行在堆叠空间之外, 它们会得到可怕的“ 堆叠过流” 例外, 从而崩溃。 因此, OCaml 程序员必须小心, 当他们写出循环函数时, 要留在所谓的 _ latter- recurive_ 碎片中, 使用不消耗堆叠空间的 _tail_ 调用。 这个纪律是计算堆堆叠空间的一个困难来源。 开始者必须学习循环, 然后尾盘再翻。 专家对写“ List. mapp ” 的“ 正确” 方式有异议。 直接版本必须漂亮但不是尾盘, 所以它会崩溃的转换过程会( L) 比直接版本要慢一些, 专家可能想要避免所有成本。 有些图书馆会提出可怕的执行方法, 但是会滚动的代码, 来弥补这种损失。 在一般情况下, 尾盘翻转程序运行的功能需要手动程序执行。