Reputation: 325
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
Upvotes: 1
Views: 181
Reputation: 2307
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.
Upvotes: 1
Reputation: 2901
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.
Upvotes: 0
Reputation: 2345
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.
Upvotes: 1