sobad2009
sobad2009

Reputation: 11

How to count a number on in Elixir without built in function such as Enum.count?

How to count a number on in Elixir without built-in function such as Enum.count. Here is my code, Thanks so much

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

Upvotes: 0

Views: 936

Answers (2)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

While the answer by Adam is perfectly correct, to calculate the average you might do better (in one loop,) using more sophisticated accumulator.

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 

Here we do accumulate both count and total and calculate an average on the last step when the list is exhausted.

Also, you might return everything, as a tuple {cnt, sum, sum / cnt}, or as a map for better readability.

Upvotes: 0

Adam Millerchip
Adam Millerchip

Reputation: 23139

You should read about tail-call optimization. The compiler makes use of this optimisation to prevent a new stack frame being created every recursive call, which will happen in your code. Here is an example of how to write the sum/1 function in a tail-recursive way. The main idea is to keep the return in an accumulator variable that is passed to each call, instead of building up the answer in the call stack:

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

For count, you can do something similar, but just add 1 instead of the value of the list item:

def count(list), do: count(0, list)
def count(acc, []), do: acc
def count(acc, [_head | tail]), do: count(acc + 1, tail)

Upvotes: 3

Related Questions