Elixir:条件语句内的递归能否实现尾调用优化?
你的Elixir递归函数会被尾调用优化吗?
关于你编写的poller函数
你的poller函数会被尾调用优化。
在:try_again分支中,执行完:timer.sleep(interval)后,递归调用poller(func, args, interval)是该分支的最后一个操作——这个调用的返回值直接作为当前函数调用的返回值,没有任何后续代码需要处理它的结果。而:done分支直接返回:done,不涉及递归逻辑。BEAM(Elixir/Erlang的虚拟机)会识别这种符合尾调用特征的递归,不会为每次递归调用创建新的栈帧,避免栈溢出问题。
条件语句中的尾调用优化规则
尾调用优化的核心判断标准始终是:递归调用是否是当前代码路径的最后执行操作,和它处于case分支、if的do块还是else块无关。
举几个典型场景说明:
有效优化的场景:
def conditional_recurse(n) do if n > 0 do # 递归是if块的最后操作,也是当前代码路径的最终操作 conditional_recurse(n - 1) else :finished end end当
n > 0时,递归调用是该路径的最后一步,会被尾调用优化;n <= 0时直接返回:finished,不影响优化逻辑。无法优化的场景:
def non_tail_recurse(n) do val = if n > 0 do non_tail_recurse(n - 1) else 0 end # 递归调用的返回值还要参与后续计算,不是最后操作 val + 1 end这里递归调用的结果会被用来执行
val + 1,所以递归不是当前代码路径的最后操作,无法触发尾调用优化。
简单来说:只要在某个条件分支里,递归调用执行后没有任何需要处理其返回值的后续代码,BEAM就会对这个递归调用进行尾调用优化,其他分支的逻辑不影响该分支的优化判定。
内容的提问来源于stack exchange,提问作者darshandzend
相关产品推荐
相关产品推荐

