这是尾递归吗?

时间:2016-02-07 20:15:56

标签: elixir

我有以下代码段:

def flatten([h|t]), do: [h] ++ flatten(t)

我在fp世界中很新,想知道这是否是尾递归?

1 个答案:

答案 0 :(得分:8)

这不是尾递归。为了运行最后一个表达式(++,列表连接),必须保留[h]并且对flatten(t)的新调用将导致新的堆栈帧,而不能只是因为引用[h]而替换上一个。

换句话说,通过尾调用优化,顶级函数调用将替换先前的堆栈。该函数调用中的任何表达式都是事先发生的,并且在调用它们时会增加堆栈。

尾部调用优化的大多数类型的枚举(包括尾递归)都使用累加器。要利用@ GavinBrelstaff的代码,这是尾递归形式:

defmodule RC do
  def flatten(list, acc \\ [])
  def flatten([], acc), do: Enum.reverse(acc)
  def flatten([h|t], acc) when is_list(h), do: flatten(h++t, acc)
  def flatten([h|t], acc), do: flatten(t, [h|acc])
end

这里的无体函数子句只是将[]建立为默认累加器。因为我们总是在前面,为了保持秩序,我们必须在完成后撤销列表。这是非常常见的事情,Enum.reverse在VM中进行了高度优化。