I've found a need to write a lazy version of `Access.key/2` when traversing nested structures where providing a default value might be expensive.
```elixir defmodule Book, do: defstruct([:name, :isbn_13, :author]) defmodule Author, do: defstruct([:name, :related_works]) defmodule RelatedWorks, do: defstruct([:books, :papers, :music]) book = %Book{ name: "Programming Erlang, Second Edition", isbn_13: "978-1-937785-53-6", author: %Author{name: "Joe Armstrong", related_works: nil} } related_works = Kernel.get_in( book, [ Access.key(:author, fn -> lookup_author(book) end), Access.lazy_key(:related_works, fn -> lookup_related_works(book) end), Access.key(:books, []) ] ) ``` For my use-case I also needed to differentiate between `nil` fields on structs vs maps, so I added the third parameter for an anonymous function that takes in the result of `Map.fetch/2` and returns whether or not to substitute the value with a default. Here's the full implementation: ```elixir @spec lazy_key( key, (-> term), (map | struct, {:ok, term} | :error -> boolean) ) :: access_fun( data :: struct | map, current_value :: term ) def lazy_key( key, default_fn \\ fn -> nil end, use_default? \\ fn data, {:ok, nil} when is_struct(data) -> :replace _, {:ok, value} -> {:keep, value} _, :error -> :replace end ) do fn :get, data, next -> value = fetch_or_default(data, key, default_fn, use_default?) next.(value) :get_and_update, data, next -> value = fetch_or_default(dt ata, key, default_fn, use_default?) case {data, next.(value)} do {_data, {get, update}} -> {get, Map.put(data, key, update)} {data, :pop} when is_struct(data) -> {value, Map.put(data, key, nil)} {data, :pop} -> {value, Map.delete(data, key)} end end end defp fetch_or_default(data, key, default_fn, use_default?) do with fetch_result <- Map.fetch(data, key), {:keep, value} <- use_default?.(data, fetch_result) do value else :replace -> default_fn.() end end ``` I was about to open a PR to add in the implementation but then I saw that I should propose the idea here first (it's my first time submitting a proposal). I'd love to hear your thoughts on the idea. – Ocean -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/elixir-lang-core/8032f0f1-e252-4c97-9f56-fa73fcaa6704n%40googlegroups.com.