简体   繁体   English

有没有办法明确地写一个elixir函数进行尾调用优化?

[英]Is there a way to explicitly write a elixir function to be tail call optimised?

In Clojure for example you can use the recur especial form to explicit the intention to use non-stack-consuming recursive calls, and is verified by the compiler. 例如,在Clojure中,您可以使用recur especial形式来明确使用非堆栈消耗递归调用的意图,并由编译器进行验证。 As it's wrote in the Clojure docs : 正如它在Clojure 文档中所写:

"recur in other than a tail position is an error", "recur is functional and its use in tail-position is verified by the compiler" “在尾部位置以外的地方重复是一个错误”,“重复是功能性的,并且它在尾部位置的使用由编译器验证”

In elixir you can define a function as a series of clauses, with recursions calls between them. 在elixir中,您可以将函数定义为一系列子句,并在它们之间进行递归调用。 Is there a way to know for sure that the defined function is going to be tail call optimised? 有没有办法确定定义的函数将被尾部调用优化?

Compiler doesn't optimize a function . 编译器不优化函数 It optimizes a call to that function. 它优化了对该函数的调用 It may be the call to the same function inside it, it may be a call to different function, it doesn't matter. 它可能是对它内部相同函数的调用,它可能是对不同函数的调用,也没关系。

...which isn't the case with Clojure, where recur can only return execution to the latest "recursion point" (be it loop or fn ) which makes mutual recursion impossible without "help from the outside", such as a trampoline . ...这与Clojure的情况并非如此,其中recur只能将执行返回到最新的 “递归点”(无论是loop还是fn ),这使得在没有“来自外部的帮助”(例如蹦床)的情况下相互递归是不可能的。 It's more like a bandaid than a solution, but the problem is too big and a proper solution would require too much. 它更像是一个bandaid而不是一个解决方案,但问题太大了,一个合适的解决方案需要太多。

Yes, there is a way to make sure it gets optimized in Elixir: it needs to be an actual tail call . 是的,有一种方法可以确保它在Elixir中得到优化: 它需要是一个真正的尾调用 That's all. 就这样。

In computer science, a tail call is a subroutine call performed as the final action of a procedure. 在计算机科学中,尾调用是作为过程的最终动作执行的子例程调用。

This can easily be determined by visually inspecting the code. 这可以通过目视检查代码轻松确定。

If Clojure were to work this way, the following two definitions would be equivalent: 如果Clojure以这种方式工作,以下两个定义将是等效的:

(defn x [] (x))     ; <- StackOverflowError if called
(defn x [] (recur)) ; <- hangs if called

But if you want to enforce this and fail otherwise, you have to do it either: 但是如果你想强制执行此操作而失败,则必须执行以下操作:

  • before compilation, eg with static code analyis using some markings for "desired TCO" 在编译之前,例如使用静态代码分析,使用一些“期望TCO”标记
  • before deployment, eg with tests that would trigger stack overflow 在部署之前,例如使用会触发堆栈溢出的测试

The latter seems more practical, easiest with pure functions. 后者似乎更实用,最简单的纯功能。

I haven't found any existing solutions that do that. 我还没有找到任何现有的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM