Getting a default value from a Map

Published on Dec 04, 2016

I ran into a interesting gotcha while using Map.get/3.

Map.get/3 is defined as: get(map, key, default \\ nil)

The examples in the documentation demonstrate its usage and behaviour.

iex> Map.get(%{}, :a)
nil
iex> Map.get(%{a: 1}, :a)
1
iex> Map.get(%{a: 1}, :b)
nil
iex> Map.get(%{a: 1}, :b, 3)
3

What I glossed over was that the default value IS NOT what is returned when the value is nil.

Instead, the default value IS what is returned when the key is missing.

This is a very important distinction.

Therefore:

iex> Map.get(%{a: 1, b: nil}, :b, 3)
nil

This wasn’t what I expected. But after figuring what the issue was, the behaviour now seems obvious. After all, Ruby works the same way.

irb> {a: 1}.fetch(:b, 3)
3
irb> {a: 1, b: nil}.fetch(:b, 3)
nil

To set a default value from a map when the value is nil just use the normal falsy trick.

iex> Map.get(%{a: 1, b: nil}, :b) || 3
3