BadFunctionError expected a function

Viewed 112

I am trying to implement a function that takes a list and a function as it's parameters, and then the function is applied to each element of the list and then sums the result, but every time I run the program in iex, I get the error - ** (BadFunctionError) expected a function, got: 1. I can't seem to figure out what the problem is. I'm new to Elixir and functional programming.

defmodule MyList do
  def mapsum([], _func) do
    0
  end

  def mapsum([head | tail], func) do
    func.(head) + mapsum(tail, func.(head))
  end
end
2 Answers

I figured it out, the issue was func.(head) parameter inside mapsum's function body.

defmodule MyList do
  def mapsum([], _func) do
    0
  end

  def mapsum([head | tail], func) do
    func.(head) + mapsum(tail, func)
  end    
end

Please note that Mohamed’s answer, although it’s somewhat correct, is not Tail Call Optimized, and hence it might blow the stack up.

Here is a TCO’ed version.

defmodule MyListTCO do
  def mapsum(list, func, acc \\ 0)

  def mapsum([], _, acc), do: acc

  def mapsum([head | tail], func, acc),
    do: mapsum(tail, func, acc + func.(head))
end

And while the original version might have crashed on huge inputs, because the stack gets exhausted, this one would happily return.

Luckily enough, compiler is smart enough to optimize the call above to be TCO’ed, because it can do it. But it is still always better to not rely on the compiler and keep this in mind.

Related