6

我正在用 Elixir 写一个简单的例子,虽然它有效,但我不太明白如何。

defmodule MyList do
  def sum([],acc \\ 0), do: acc
  def sum([head | tail], acc), do: sum(tail,acc + head)
end

当我调用 MyList.sum 时,我得到了预期的结果

sum([]) => 0
sum([1,2,3]) => 6

我无法在第二个总和中添加默认参数,因为编译器会抛出错误

def sum/2 has default values and multiple clauses, use a separate clause for declaring defaults

所以我的问题是, sum([1,2,3]) 是如何工作的?它与任何定义都不匹配。函数仍然是尾递归的吗?

4

1 回答 1

9

当您有一个带有可选参数的多子句时,您可以将默认值指定为无正文子句:

defmodule MyList do
  def sum(list, acc \\ 0) # sets up default arguments

  def sum([],acc), do: acc
  def sum([head | tail], acc), do: sum(tail,acc + head)
end

关于您的示例,我只是在猜测,但我认为您的代码类似于以下内容:

defmodule MyList do
  # implicitly generated due to default argument
  def sum(list), do: sum(list, 0)

  def sum([],acc), do: acc
  def sum([head | tail], acc), do: sum(tail,acc + head)
end

这就是为什么sum([1,2,3])也有效。

编辑:该函数绝对是尾递归的。如果一个函数做的最后一件事是调用另一个函数(或它自己),那么它就是一个尾调用。所以在这种情况下,当我们调用 时sum(tail, acc + head),首先计算参数,然后进行尾递归调用。

于 2014-03-04T08:16:42.317 回答