Tuesday, December 21, 2021

Elixir: if key exists: update, otherwise: assoc

Remember Clojure: if key exists: update, otherwise: assoc? Let's do that with Elixir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@doc """
If `key` exists in `map`, updates its value (assumed to be a list) by concatenating `value`.
If `key` does not exist in `map`, creates `{key => [value]}` in `map`.
## Examples
 
  iex(35)> Tap.Worker.update_conj!(%{a: [1]}, :a, 2)
  %{a: [1, 2]}
 
  iex(36)> Tap.Worker.update_conj!(%{a: [1]}, :b, 2)
  %{a: [1], b: [2]}
 
"""
@spec update_conj!(map, any, any) :: map
def update_conj!(map, key, value) when is_map(map) do
  Map.update(map, key, [value], fn
    existing_values when is_list(existing_values) ->
      existing_values ++ [value]
 
    existing_value ->
      raise(ArgumentError, "Value is not a list: #{inspect(existing_value)}")
  end)
end