Reputation: 11
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
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
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