Skip to content

Instantly share code, notes, and snippets.

@aaron-price
Created June 16, 2021 01:26
Show Gist options
  • Save aaron-price/9d33186c7887d03628a08b4bc548e4fa to your computer and use it in GitHub Desktop.
Save aaron-price/9d33186c7887d03628a08b4bc548e4fa to your computer and use it in GitHub Desktop.
naive_put_in.ex
defmodule NaivePutIn do
@doc """
### What problem does this solve?
Sometimes I need a deeply nested map. Maps ALL THE WAY DOWN!
If I can safely assume every step is a map, I should be able to do this:
iex(0)> put_in(%{}, [:a, :b, :c], "V")
** (ArgumentError) could not put/update key :b on a nil value
(elixir 1.10.4) lib/access.ex:365: Access.get_and_update/3
(elixir 1.10.4) lib/map.ex:837: Map.get_and_update/3
(elixir 1.10.4) lib/kernel.ex:2329: Kernel.put_in/3
Behold! The solution:
iex(1)> NaivePutIn.naive_put_in(%{}, [:a, :b, :c], "V")
%{a: %{b: %{c: "V"}}}
"""
def naive_put_in(m, path, v, acc \\ [])
def naive_put_in(m, [], v, acc), do: put_in(m, acc, v)
def naive_put_in(m, [hd | tl], v, acc) do
curr_path = acc ++ [hd]
m = case get_in(m, curr_path) do
nil -> put_in(m, curr_path, %{})
_ -> m
end
naive_put_in(m, tl, v, curr_path)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment