Optional default value for get_in Access behavior elixir

Cyzanfar Source

Is there an option to add a default fallback value in get_in/2?

Scenario:

merge_maps = get_in(
  payload, ["msg", "clicks"]
) ++ get_in(
  payload, ["msg", "opens"]
)

if the key "clicks" or "opens" isn't found in the nested "msg" map, get_in/2 will return nil which then thrown an error:

** (ArgumentError) argument error
    :erlang.++(nil, nil)
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (iex) lib/iex/evaluator.ex:250: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:230: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:208: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:94: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:24: IEx.Evaluator.init/4

Would be nice to be able to do something like

get_in(payload, ["msg", "clicks"], [])

where the empty list would be the fallback value if no value with that key is found. What's the right way to achieve this?

Update

Thanks to the answer from @PatNowak I implemented a wrapper around get_in:

defmodule Helpers.AccessHelper do
  def get_in_attempt(data, keys, default \\ []) do
    case get_in(data, keys) do
      nil -> default
      result -> result
    end
  end
end

And then in another file:

import Helpers.AccessHelper, only: [get_in_attempt: 2]

merge_maps = get_in_attempt(
  payload, ["msg", "clicks"]
) ++ get_in_attempt(
  payload, ["msg", "opens"]
)
elixirphoenix-framework

Answers

answered 6 months ago PatNowak #1

You can write your own wrapper for Kernel.get_in/2, but with using default value as a fallback.

def get_in_attempt(data, keys, default) do
  case get_in(data, keys) do
    nil-> default
    result -> result
  end
end

so in your case it's enough to have

def get_in_attempt(data, keys) do
  case get_in(data, keys) do
    nil-> [] # your default is set, so don't need to pass it
    result -> result
  end
end

However, using first approach (with explicit default argument is more flexible and can be reused in different scenarios).

comments powered by Disqus