elixir - 是尾递归吗

标签 elixir

我有以下代码片段:

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

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

最佳答案

那不是尾递归。为了运行最后一个表达式( ++ ,列表连接), [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

这里的 bodyless 函数子句只是将 [] 建立为默认累加器。因为我们总是在前置,为了保持顺序,我们必须在完成后反转列表。这是很常见的事情,并且 Enum.reverse 在 VM 中进行了高度优化。

关于elixir - 是尾递归吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35258566/

相关文章:

elixir - 如何使用 Ecto 测试唯一性约束

sql - 在 SQL 连接查询期间计算 Ecto 中的虚拟字段

elixir - Ecto 模型 `undefined function: ` 使用宏时 *** 在 iex 中***

elixir - 如何别名在mix.exs中运行两次?

asynchronous - 异步 Elixir 与异步 Julia

elixir - 如何使用 exrm 在集群上推送新的 Elixir 版本?

elixir - 避免 Eex 中的 JSON 转义

elixir - 使用 Poison 将映射编码为 json 时对键进行排序

elixir - key :user_id not found in. Elixir 预加载问题

elixir - 将 Phoenix 请求路径与数据库中定义的 Route 匹配