Extractable protocol (Extractable v1.0.1) View Source

Extractable is a simple protocol that allows for the extraction of elements from a collection, one element at a time.

This is the major difference with the Enumerable protocol: Enumerable only works with whole collections at a time, so extracting a few items and then returning the rest of the unconsumed collection is impossible.

This is exactly what Extractable does allow. Extractable is however slower if used repeatedly, because the wrapping/unwrapping of certain structures has to happen once per extracted element, rather than once per collection.

Link to this section Summary

Types

t()

This type is managed by TypeCheck, which allows checking values against the type at runtime.

Functions

Extractable.extract/2 returns {:ok, {item, collection}} if it was possible to extract an item from the collection. {:error, reason} is returned when no element can be extracted.

Link to this section Types

Specs

t()

This type is managed by TypeCheck, which allows checking values against the type at runtime.

Full definition:

head (opaque type)

Link to this section Functions

Specs

extract(t()) :: {:ok, {any(), t()}} | {:error, any()}

Extractable.extract/2 returns {:ok, {item, collection}} if it was possible to extract an item from the collection. {:error, reason} is returned when no element can be extracted.

The following error reasons are standardized:

  • :empty: the collection is empty, and an element needs to be inserted first before extracting would work.

Other reasons might be used if it makes sense for your collection.

Extraction Order

What item is extracted depends on the collection: For collections where it matters, the most logical or efficient approach is taken. Some examples:

  • For Lists, the head of the list is returned as item.
  • For Maps, an arbitrary {key, value} is returned as item.
  • For MapSets, an arbitrary value is returned as item.
  • For Ranges the first item of the range is returned.

Examples

iex> Extractable.extract([])
{:error, :empty}

iex> Extractable.extract([1, 2, 3])
{:ok, {1, [2, 3]}}

iex> Extractable.extract(%{a: 1, b: 2, c: 3})
{:ok, {{:a, 1}, %{b: 2, c: 3}}}

iex> Extractable.extract(MapSet.new())
{:error, :empty}

iex> {:ok, {elem, result}} = Extractable.extract(MapSet.new([1, 2, 3]))
iex> elem
1
iex> result
#MapSet<[2, 3]>

iex> Extractable.extract(200..100)
{:ok, {200, 199..100}}

iex> Extractable.extract(42..42)
{:ok, {42, 43..42//1}}