PassiveSupport.Item.dig

You're seeing just the function dig, go back to PassiveSupport.Item module for more information.
Link to this function

dig(item, path \\ [], default \\ nil)

Specs

dig(traversable(), key_or_index() | [key_or_index()], t()) :: t()

Traverses into item through an arbitrary path of keys and indices.

Think of dig/3 as an extension of the concept at the heart of Access.get/3. There are times when the data you're working with is a deeply-nested structure, and your bigger concern is what a specific part of that data looks like. In cases where you are working with one sort of data type (e.g., maps, structs, tuples, or lists), then you know you can use the same function or macro to dig down through each successive layer of nested data. However, when working with disparate data types, keeping track of the structure of each level of the nested data becomes an exercise in both patience, and trial and error.

The assurance dig/3 provides is that, until arriving at a leaf node within item or fully traversing through path, the function will retrieve the element of item at the next point within path, dispatching to the correct function for doing so based on the structure of the data at the current level of traversal. If dig arrives at a nil value at any point in traversal, the remainder of the path is dropped, and the value provided as default (which, by custom, defaults to nil itself) is immediately returned to the caller.

Note: The only event in which this function will raise an exception is when it attempts to traverse the path of a scalar value. To guarantee consistency in the traversal rules, trying to traverse a tuple with an out-of-bounds index results in nil being returned instead of an ArgumentError being raised. Similarly, attempting to dig into a struct at a keyword that it doesn't define will return nil instead of raising a KeyError. For exception propagation, use dig!/3 instead.

Examples

iex> pets = %{
...>   cats: [
...>     %{name: "Lester", favorite_toy: "feather"},
...>     %{name: "Janice", favorite_toy: "laser pointer"}
...>   ],
...>   dogs: [
...>     %{name: "Scrump", favorite_toy: "rope"},
...>     %{name: "Stitch", favorite_toy: "ball"}
...>   ],
...>   hyenas: [
...>     %{"what is this" => "oh no", "hyenas can't be pets" => "too wild"}
...>   ]
...> }
iex> dig(pets, [:dogs])
[%{name: "Scrump", favorite_toy: "rope"}, %{name: "Stitch", favorite_toy: "ball"}]
iex> dig(pets, [:cats, 1])
%{name: "Janice", favorite_toy: "laser pointer"}
iex> dig(pets, [:hyenas, 0, "what is this"])
"oh no"
iex> dig(pets, [:dogs, 0, :favorite_food, :ingredients])
nil

You can also use dig through lists of nested data structures by passing an empty list [] as a part of path.

iex> connor_family = [
...>  {"Sarah", %{favorite_movies: ["Dr. Strangelove", "China Town", "Citizen Kane"]}},
...>  {"John", %{favorite_movies: ["Tron", "Star Wars", "The Fifth Element"]}},
...>  {"Cameron", %{favorite_movies: ["Robocop", "Logan's Run", "The Animatrix - The Second Renaissance Part 2"]}}
...> ]
iex> dig(connor_family, [[], 1, :favorite_movies, 2])
["Citizen Kane", "The Fifth Element", "The Animatrix - The Second Renaissance Part 2"]