Return a grouped sum from a list I just started with Elixir and this is what I have now. Is there an easier or better way to write this?

defmodule GroupBySum do
  def sum(col), do: sum(%{}, col)
  defp sum(r, [h|t]) do
    {k, v} = h
    r = r |&gt; Dict.update(k, v, fn(val) -&gt; val + v end)
    sum(r, t)
  end
  defp sum(r, []), do: r
end

list = [a: 1, b: 2, c: 3, a: 2, b: 1, c: 0]
IO.inspect GroupBySum.sum(list) #%{a: 3, b: 3, c: 3}
It can be done several ways.  Instead of explicitly using recursion we can, as @alxndr suggested, make use of the recursion capabilities of the Enum module.  I am going to use Enum.map_reduce simply because I find it useful when troubleshooting to key the items and the accumulator in that form.

In general the solution is the same as yours.

  def sum(list) do
    list |&gt; Enum.map_reduce([],
      fn({key, val}, acc) -&gt;
        {{key, val}, Keyword.update(acc, key, val, &amp;(&amp;1 + val))}
      end
    ) |&gt; elem(1)
  end


The anonmous function in map_reduce accepts and item and an accumulator.  Since the item is a keyword list, it has the form {key,val} so I match that  in the function definition.  The return from this function must be a tuple with the accumulator as the second value.  For testing purposes I returned the same {key, val} as the first item.  The Keyword.update function is the accumulator.  A form of this same routine that helps the intermediate values be visible is:

def sum(list) do
  list |&gt; Enum.map_reduce([],
    fn({key, val}, acc) -&gt;
      x = Keyword.update(acc, key, val, &amp;(&amp;1 + val))}
      IO.inspect(x)
      {{key, val}, x}
    end
  ) |&gt; elem(1)
end


In the case of the input you provided, the IO.inspect helps me understand how the routine collected the desired result, as seen below.

[a: 1]
[a: 1, b: 2]
[a: 1, b: 2, c: 3]
[a: 3, b: 2, c: 3]
[a: 3, b: 3, c: 3]
[a: 3, b: 3, c: 3]
[a: 3, b: 3, c: 3]


I found this a fun exercise -- thanks for posting.