1
votes

I'm pretty new to elixir and functional programming in general and I am having a map of the form:

key => [int, int]

for example:

14 => [1,0]

Using the snippet below, I have managed to increase the value of 1 in [1,0] by 1 but I don't manage to do the same for the second value, aka '0'.

This is my working sample code for the head of the list

iex(2)> a = Map.update!(a, 'b', fn([a|b]) -> [a+1] ++ b end) 

This is my code and the error I get for the second element of the list, please note that my list is only consisting of 2 elements and this is not going to change

iex(3)> a = Map.update!(a, 'b', fn([a|b]) -> a ++ [b+1] end) 
** (ArithmeticError) bad argument in arithmetic expression
    :erlang.+([0], 1)
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:228: :erl_eval.expr/5
    (stdlib) erl_eval.erl:470: :erl_eval.expr/5
    (elixir) lib/map.ex:727: Map.update!/3
3

3 Answers

1
votes

On the second case when you match on [a|b] = [1,0], a will be an integer (1) and b will be a list ([0]). In order to increase b with that function, all you'd have to do update your matching part and how you handle a and b:

a = Map.update!(a, 'b', fn([a,b]) -> [a] ++ [b+1] end) 

Alternatively you can also do

a = Map.update!(a, 'b', fn([a,b]) -> [a, b+1] end) 

To construct the updated list.

1
votes

If you want to update all keys of the map, use Enum.map like this:

the_map
|> Enum.map(fn {k, [v1, v2]} -> {k, [v1+1, v2+1]} end)
|> Enum.into(%{})

Note that Enum.map will return a list (keyword list in this case), so you need to put data back into a map.

0
votes

This is because the tail of the list is a list:

iex(2)> [h | t] = [1, 0]
[1, 0]
iex(3)> h
1
iex(4)> t
[0]

When you take a look on your error description, :erlang.+([0], 1) it shows that you want to add [0] to 1.

If you want to pattern match the list with exactly two elements, you may do:

fn([a, b]) -> [a + 1, b + 1] end

However, in such cases it would be better to use tuples.