【问题标题】:What are the pros and cons of these different function definitions?这些不同的函数定义的优缺点是什么?
【发布时间】:2016-08-08 01:43:38
【问题描述】:

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

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

谢谢!

  @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

【问题讨论】:

  • 我非常想更改您问题的标题,但这似乎可能是编辑过度。请让您的问题的标题更具描述性。
  • 很公平......你能给我你会使用的标题吗?
  • 我想到的是“多功能头是解决这个问题的更好方法吗?”您现有的标题非常通用。
  • 嗯,这不是我想说的......你怎么看:“这些不同的函数定义的优缺点是什么”
  • “这些不同的函数定义有什么优缺点?”对我来说听起来不错。

标签: elixir


【解决方案1】:

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

它们之间的一个重要区别是第一个和第三个实现是tail recursive,而第二个不是。这意味着第二个实现将使用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

这与第一个实现几乎相同。

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      相关资源
      最近更新 更多