Как рассчитать число в Elixir без встроенной функции, такой как Enum.count? - PullRequest
0 голосов
/ 24 февраля 2020

Как рассчитать число в Elixir без встроенной функции, такой как Enum.count. Вот мой код, Большое спасибо

defmodule Ans do
  @my_favorite_number 0

 def sum([]) do
    0
  end
  def sum([head|tail]) do
    head + sum(tail)

  end

  def average([head|tail]) do
    total = sum([head|tail])
    iterations = Enum.count([head|tail])
    output = total / iterations
  end

  end

Ответы [ 2 ]

3 голосов
/ 24 февраля 2020

Вы должны прочитать об оптимизации хвостового вызова. Компилятор использует эту оптимизацию, чтобы предотвратить создание нового стекового фрейма при каждом рекурсивном вызове, который произойдет в вашем коде. Вот пример того, как написать функцию sum/1 хвостовой рекурсией. Основная идея состоит в том, чтобы сохранить возврат в переменной accumulator, которая передается каждому вызову, вместо создания ответа в стеке вызовов:

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

Для count вы можете сделать что-то аналогично, но просто добавьте 1 вместо значения элемента списка:

def count(list), do: count(0, list)
def count(acc, []), do: acc
def count(acc, [_head | tail]), do: count(acc + 1, tail)
0 голосов
/ 24 февраля 2020

Хотя ответ Адама совершенно верен, для вычисления среднего вы могли бы добиться большего успеха (за один л oop,), используя более сложный аккумулятор.

defmodule M do
  def avg(list), do: do_avg({0, 0}, list)

  defp do_avg({cnt, sum}, []),
    do: sum / cnt
  defp do_avg({cnt, sum}, [h | t]),
    do: do_avg({cnt + 1, sum + h}, t)
end 

M.avg [1,2,3,4]
#⇒ 2.5 

Здесь мы накапливаем и счет и общее количество и вычисляем среднее значение на последнем шаге, когда список исчерпан.

Кроме того, вы можете вернуть все, как кортеж {cnt, sum, sum / cnt} или как карта для лучшей читаемости.

...