TaggedTuple (TaggedTuple v1.0.0) View Source

A library to work with tagged tuples.

Tagged tuple is a tuple attaching a tag to a value {tag, value}. Common tagged tuples are {:ok, value} and {:error, message} returned from the functions.

Tag chains

A chain of tags can be attached to a single core value by nesting tagged tuples in each other.

For example, {:units, {:boxes, 1}} and {:units, {:kilograms, 2.5}} tagged tuples describe the same deliverable item with different measures.

The tag chains of :units - :boxes and :units - :kilograms can be efficiently pattern matched then to handle core values of different types appropriately.

Link to this section Summary

Functions

Defines a tagged tuple. It's equivalent to {tag, value}.

Returns the tag chain and the core value from the given tagged tuple.

Returns a tagged tuple by attaching the tag chain to the core value.

Removes the given subchain from the tag chain's beginning and return the tagged tuple built from the rest. When the full tag chain is given, it returns the core value.

Link to this section Functions

Defines a tagged tuple. It's equivalent to {tag, value}.

The operator is right-associative. When it's called several times in a row, it assembles a tag chain with a value in the core.

:x --- :y --- :z --- "value" == {:x, {:y, {:z, "value"}}}

Can be used in Expressions and Pattern Matchings.

Examples

iex> use TaggedTuple
...> :tag --- 12
{:tag, 12}
...> tagged_tuple = :a --- :tag --- :chain --- 12
{:a, {:tag, {:chain, 12}}}
...> match?(:a --- :tag --- _tail, tagged_tuple)
true
...> :a --- t1 --- t2 --- core_value = tagged_tuple
...> t1 == :tag
...> t2 == :chain
...> core_value == 12
Link to this function

from_list(list, tag_fun \\ fn x -> x end, value_fun \\ fn y -> y end)

View Source

Converts a list to a tagged tuple.

The list must have at least two elements, a tag and a value, respectfully.

The tag_fun will be invoked with each tag, and the result will be added to the tuple. The value_fun will be invoked with the core value, and the result will be added to the tuple.

Examples

iex> TaggedTuple.from_list([:a, :tag, :chain, 2])
{:a, {:tag, {:chain, 2}}}

iex> TaggedTuple.from_list(["a", "tag", "chain", 200], &String.to_existing_atom/1, &div(&1, 100))
{:a, {:tag, {:chain, 2}}}
Link to this function

from_map(map, tag_fun \\ fn x -> x end, value_fun \\ fn y -> y end)

View Source

Converts a map to a tagged tuple.

The tag_fun will be invoked with each tag, and the result will be added to the tuple. The value_fun will be invoked with the core value, and the result will be added to the tuple.

Examples

iex> TaggedTuple.from_map(%{a: %{tag: %{chain: 2}}})
{:a, {:tag, {:chain, 2}}}

iex> TaggedTuple.from_map(%{"a" => %{"tag" => %{"chain" => 20}}}, &String.to_existing_atom/1, &div(&1, 10))
{:a, {:tag, {:chain, 2}}}

Returns the tag chain and the core value from the given tagged tuple.

Examples

iex> {chain, value} = TaggedTuple.split({:a, {:tag, {:chain, 2}}})
...> chain == {:a, {:tag, :chain}}
...> value == 2
iex> TaggedTuple.tag(value, chain)
{:a, {:tag, {:chain, 2}}}

Returns a tagged tuple by attaching the tag chain to the core value.

tag_chain can be a nested tuple with tags returned from the split/1 or a list with tags.

Example

iex> TaggedTuple.tag(2.5, :some_tag)
{:some_tag, 2.5}

iex> TaggedTuple.tag(7, {:a, {:tag, :chain}})
{:a, {:tag, {:chain, 7}}}

iex> TaggedTuple.tag(7, [:a, :tag, :chain])
{:a, {:tag, {:chain, 7}}}
Link to this function

to_list(tagged_tuple, tag_fun \\ fn x -> x end, value_fun \\ fn y -> y end)

View Source

Converts a tagged tuple to a list.

The tag_fun will be invoked with each tag, and the result will be inserted into the list. The value_fun will be invoked with the tagged tuple's core value, and the result will be inserted into the list.

Examples

iex> TaggedTuple.to_list({:a, {:tag, {:chain, 2}}})
[:a, :tag, :chain, 2]

iex> TaggedTuple.to_list({:a, {:tag, {:chain, 2}}}, &to_string/1, &(&1 * 100))
["a", "tag", "chain", 200]
Link to this function

to_map(tagged_tuple, tag_fun \\ fn x -> x end, value_fun \\ fn y -> y end)

View Source

Converts a tagged tuple to a map.

The returned map can be encoded into a JSON to transmit over the network or persist in a database.

The tag_fun will be invoked with each tag, and the result will be inserted into the map. The value_fun will be invoked with the tagged tuple's core value, and the result will be inserted into the map.

Examples

iex> TaggedTuple.to_map({:a, {:tag, {:chain, 2}}})
%{a: %{tag: %{chain: 2}}}

iex> TaggedTuple.to_map({:a, {:tag, {:chain, 2}}}, &to_string/1, &(&1 * 100))
%{"a" => %{"tag" => %{"chain" => 200}}}
Link to this function

untag(tagged_tuple, tag_chain)

View Source

Same as untag!/2.

Returns {:error, :mismatch} when tag_chain doesn't match the beginning part of the tag chain of the tagged tuple.

Link to this function

untag!(tagged_tuple, tag_chain)

View Source

Removes the given subchain from the tag chain's beginning and return the tagged tuple built from the rest. When the full tag chain is given, it returns the core value.

Raises ArgumentError exception if the passed tag subchain doesn't match the begginning of the tag chain of the tagged tuple.

tag_chain can be a nested tuple with tags returned from the split/1 or a list with tags.

Examples

iex> value = {:a, {:tag, {:chain, 2}}}
iex> TaggedTuple.untag!(value, :a)
{:tag, {:chain, 2}}
iex> TaggedTuple.untag!(value, {:a, :tag})
{:chain, 2}
iex> TaggedTuple.untag!(value, {:a, {:tag, :chain}})
2
iex> TaggedTuple.untag!(value, [:a, :tag, :chain])
2
iex> value = {:other, {:stuff, 2}}
...> TaggedTuple.untag!(value, {:a, {:tag, :chain}})
** (ArgumentError) Tag chain {:a, {:tag, :chain}} doesn't match one in the tagged tuple {:other, {:stuff, 2}}.