这些不同功能定义的优缺点是什么?

时间:2016-04-26 16:57:31

标签: elixir

我目前正在学习elixir,我想知道这三个实现是否真的是一个选择问题,或者有一些与性能或其他事情有关的最佳实践,换句话说是否有最好的实现?

我的第一个实现是第三个(...我知道),但如果我必须选择,我将明确选择第二个。第一个对我来说似乎很奇怪,因为我将函数定义了3次

Thx!

  @spec count(list) :: non_neg_integer
  def count(l), do: count(l, 0)
  defp count([], acc), do: acc
  defp count([_ | tail], acc), do: count(tail, acc + 1)


  @spec count(list) :: non_neg_integer
  def count(l) do
      case l do
          [] -> 0
          [_|tail] -> 1 + count(tail)
      end
  end


@spec count(list) :: non_neg_integer
  def count(l) do
      do_count(l, counter)
  end

  defp do_count(list, counter \\ 0) do
      cond do
          list == [] -> counter
          true ->
              counter = counter + 1
              do_count(tl(list), counter)
      end
  end

2 个答案:

答案 0 :(得分:8)

  

我想知道这三个实现是否真的是一个选择问题,或者有一些与性能或其他事情相关的最佳实践,换句话说是否有最好的实现?

它们之间的一个重要区别是第一个和第三个实现是tail recursive,而第二个实现不是{{3}}。这意味着第二个实现将使用O(n)内存在n元素列表上执行,而第一个和第三个将使用O(1)

第三种解决方案使用cond,其中模式匹配解决方案会更短,更有可能更快。

你可以改写

cond do
  list == [] -> counter
  true ->
    counter = counter + 1
    do_count(tl(list), counter)
end

case list do
  [] -> counter
  [_|tail] ->
    counter = counter + 1
    do_count(tail, counter)
end

与第一次实施几乎相同。

第一个肯定是最惯用的,最有可能是三个中最快的。

答案 1 :(得分:0)

您始终可以将多子句函数转换为case语句,反之亦然。请注意,Elixir是一种函数式编程语言,因此编写多子句函数非常惯用。

对于cond,如果编写多子句函数需要花费太多工作,那将是最后的选择。

回到你的问题,第一个是三个中最好的。