PassiveSupport.Item.dig
dig
, go back to PassiveSupport.Item module for more information.
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"]