我有以下代码段:
def flatten([h|t]), do: [h] ++ flatten(t)
我在fp世界中很新,想知道这是否是尾递归?
答案 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中进行了高度优化。