A repository of tips and tricks (in both English and French) curated by Mirego’s engineering team.
  • elixir

Using Elixir’s `Map.get/3` third argument as a fallback value

While performing a code review, I started to reflect on how to get a specific key in an Elixir map while specifying a default fallback value.

I really like the Map.get/3 approach:

data = %{foo: "bar"}

Map.get(data, :foo, "default")
# => "bar"

Map.get(data, :foo2, "default")
# => "default"

And I was wondering why would someone use the Access behaviour + || operator approach for the same purpose:

data = %{foo: "bar"}

data[:foo] || "default"
# => "bar"

data[:foo2] || "default"
# => "default"

The end result is the same, right? Not quite! If we start messing around with the nil value for an existing key, the result will differ!

data = %{foo: "bar", baz: nil}

data[:baz] || "default"
# => "default"

Map.get(data, :baz, "default")
# => nil 😱

Map.get/3 only falls back to the default value (the third argument) if the key doesn’t exist in the map while || will fallback to the second expression if the first expression does not evaluate to a truthy value (nil is not truthy).

So there you have it, use Map.get/3 wisely: when you’re sure you’re using fallback default values when the key doesn’t exist, not just as a simple fallback for non-truthy values.