plymio_option v0.3.0 Plymio.Option.Utility View Source

Utility Function for Managing (Keyword) Options (“opts”)

Documentation Terms

In the documentation there are terms, usually in italics, used to mean the same thing (e.g. opts).

opts

opts is a Keyword.

derivable opts

derivable opts is either a Keyword or Map with Atom keys (from which the opts can be derived simply using Map.to_list/1).

key

A key is an Atom.

key list

A key list is a list of keys.

key spec

A key spec is usually a key list.

Alternatively a Map with Atom keys or a Keyword can be given and the (unique) keys will be used.

key alias dict

A key alias dict is usually a Map with Atom keys and values used for canonicalising keys (e.g. as the 2nd argument to opts_canonical_keys/2).

Alternatively a Keyword with Atom values can be given and will be converted on the fly.

key dict

A key alias dict is usually a Map with Atom keys.

Alternatively a Keyword with Atom values can be given and will be converted on the fly.

tuple predicate

A tuple predicate is an arity one function that when passed a {key,value} tuple returns true or false.

Return Values

Many functions support an API that returns either {:ok, result} or {:error, error} where error will be an Exception.

The default action for bang function when fielding {:error, error} is to raise the error.

In many cases the error will be a KeyError where its key field is set to the key, or list of keys, that is missing, unknown, etc.

Link to this section Summary

Functions

canon_keys/2 takes a key list together with a lookup dictionary and replaces each key with its canonical value from the dictionary, returning {:ok, canon_keys}

canon_keys!/2 takes a key list together with a lookup dictionary and replaces each key with its canonical value from the dictionary. Unknown keys raise a KeyError

canonical_key/2 takes a key together with a key dict and replaces the key with its canonical value from the dictionary, returning {:ok, canonical_key}

canonical_key!/2 calls canonical_key/2 and if the result is {:ok, canonical_key} returns canonical_key

canonical_keys/2 takes a key list and key alias dict and replaces each key with its canonical value from the dictionary, returning {:ok, canonical_keys}

canonical_keys!/2 calls canonical_keys/2 and if the result is {:ok, canonical_keys} returns canonical_keys

list_wrap_flat_just/1 wraps a value (if not already a list), flattens and removes nils at the first / top level

list_wrap_flat_just_uniq/1 wraps a value (if not already a list), flattens, removes nils at the first / top level, and deletes duplicates (using Enum.uniq/1)

maybe_canon_keys/2 takes a key list together with a lookup dictionary and, if the key is in the dictionary, replaces it with its value. Unknown keys are passed through unchanged

opts_avoir_keys/2 takes an opts and a key spec

opts_avoir_keys!/2 calls opts_avoir_keys/2 and if the result is {:ok, opts}, returns opts

opts_avoir_keys?/2 calls opts_avoir_keys/2 and if the result is {:ok, _}, returns true, else false

opts_canon_keys/2 takes an opts, together with either a dictionary (map) or (keyword) list of aliases

opts_canon_keys!/2 takes an opts, together with a lookup dictionary and replaces each key with its canonical value from the dictionary. Unknown keys raise a KeyError

opts_canonical_keys/2 takes a derivable opts, together with a key alias dict

opts_canonical_keys!/2 calls opts_canonical_keys/2 and if the result is {:ok, opts} returns opts

opts_create_aliases_tuples/1 takes an opts where the keys are the canonical key names, and their values are zero (nil), one or more aliases for the canonical key

opts_create_defstruct/2 takes an opts, together with a defaults map, and returns an opts where each value if the value of the key in the defaults map (with default nil)

opts_crue_defstruct/2 takes a derivable opts, together with a defaults map, and returns {:ok, opts} where each value is the value of the key in the defaults map (with default nil)

opts_drop_keys!/1 takes an opts, together with a key list and returns the opts without the supplied keys

opts_fetch_key_values/2 takes a derivable opts and a key and returns the values of the key as {:ok, values} where values will be a list

opts_fetch_key_values!/2 takes a derivable opts and a key and returns the values of the key as {:ok, values}

opts_filter/2 takes a derivable opts, together with a tuple predicate and returns {:ok, opts} where opts has all the 2tuples the tuple predicate return true for

opts_filter!/2 calls opts_filter/2 and if the result is {:ok, opts} returns opts

opts_filter_keys/2 takes a derivable opts and a key spec and returns {:ok, opts} where opts has all keys from the original derivable opts that appear in the key spec

opts_filter_keys!/2 calls opts_filter_keys/2 and if the result is {:ok, opts}, returns opts

opts_has_keys/2 takes an opts, together with a list or dictionary (map) of wanted keys

opts_has_keys!/2 calls opts_has_keys/2 and if the result is {:ok, opts}, returns opts

opts_has_keys?/2 calls opts_has_keys/2 and if the result is {:ok, _}, returns true, else false

opts_normalise/ expects a derivable opts and returns {:ok, opts}

opts_normalise!/1 calls opts_normalise/1 and if the result is {:ok, opts} returns opts

opts_normalise_map/ expects a derivable opts as argument

opts_normalise_map!/1 call opts_normalise_map/1 and if the result is {:ok, map} returns map

opts_predicate/2 takes a derivable opts, together with a tuple predicate and returns {:ok, opts} if all the 2tuples pass the tuple predicate

opts_predicate!/2 calls opts_predicate/2 and if the result is {:ok, opts} returns opts

opts_reject/2 takes a derivable opts, together with a tuple predicate and returns {:ok, opts} where opts has all the 2tuples the tuple predicate returns false for

opts_reject!/2 calls opts_reject/2 and if the result is {:ok, opts} returns opts

opts_reject_keys/2 takes a derivable opts and a key spec and returns {:ok, opts} where opts has all keys from the original derivable opts that do not appear in the key spec

opts_reject_keys!/2 calls opts_reject_keys/2 and if the result is {:ok, opts}, returns opts

opts_sort_keys/ takes a derivable opts, together with a list of sort keys, and returns the opts sorted in the sort keys order. Duplicate keys follow one after another

opts_take_keys!/1 takes an opts, together with a key list and returns the opts with just the supplied keys

opts_validate/1 returns {:ok, opts} if the argument is an opts

opts_validate!/1 calls opts_validate/1 and, if the result is {:ok, opts}, returns opts

Link to this section Types

Link to this type alias_key() View Source
alias_key() :: key()
Link to this type alias_keys() View Source
alias_keys() :: keys()
Link to this type alias_value() View Source
alias_value() :: nil | alias_keys()
Link to this type aliases_dict() View Source
aliases_dict() :: %{optional(alias_key()) => alias_key()}
Link to this type aliases_kvs() View Source
aliases_kvs() :: [{alias_key(), alias_value()}]
Link to this type aliases_tuples() View Source
aliases_tuples() :: [{alias_key(), alias_key()}]
Link to this type defaults_map() View Source
defaults_map() :: %{optional(alias_key()) => any()}
Link to this type dict() View Source
dict() :: %{optional(alias_key()) => any()}
Link to this type error() View Source
error() :: struct()
Link to this type keys() View Source
keys() :: key() | [key()]

Link to this section Functions

Link to this function canon_keys(keys, dict) View Source
canon_keys(alias_keys(), dict()) ::
  {:ok, alias_keys()} |
  {:error, error()}

canon_keys/2 takes a key list together with a lookup dictionary and replaces each key with its canonical value from the dictionary, returning {:ok, canon_keys}.

If there are any unknown keys, {:error, {canon_known_keys, unknown_keys}} will be returned.

Examples

iex> [:a, :b, :c] |> canon_keys(%{a: 1, b: 2, c: 3})
{:ok, [1,2,3]}

iex> [:a, :x, :b, :y, :c, :z] |> canon_keys(%{a: 1, b: 2, c: 3})
{:error, {[1, 2, 3], [:x, :y, :z]}}
Link to this function canon_keys!(keys, dict) View Source
canon_keys!(alias_keys(), dict()) :: alias_keys() | no_return()

canon_keys!/2 takes a key list together with a lookup dictionary and replaces each key with its canonical value from the dictionary. Unknown keys raise a KeyError.

Examples

iex> [:a, :b, :c] |> canon_keys!(%{a: 1, b: 2, c: 3})
[1,2,3]

iex> [:x] |> canon_keys!(%{a: 1, b: 2, c: 3})
** (KeyError) key :x not found in: %{a: 1, b: 2, c: 3}
Link to this function canonical_key(key, dict) View Source
canonical_key(alias_key(), any()) ::
  {:ok, alias_key()} |
  {:error, error()}

canonical_key/2 takes a key together with a key dict and replaces the key with its canonical value from the dictionary, returning {:ok, canonical_key}.

If the key is unknown, {:error, error}, error is a KeyError, will be returned.

Examples

iex> :b |> canonical_key(%{a: :p, b: :q, c: :r})
{:ok, :q}

iex> :a |> canonical_key(%{a: 1, b: 2, c: 3})
{:ok, 1}

iex> :x |> canonical_key(%{a: 1, b: 2, c: 3})
{:error, %KeyError{key: :x, term: %{a: 1, b: 2, c: 3}}}
Link to this function canonical_key!(key, dict) View Source
canonical_key!(alias_key(), dict()) :: alias_key() | no_return()

canonical_key!/2 calls canonical_key/2 and if the result is {:ok, canonical_key} returns canonical_key.

Examples

iex> :a |> canonical_key!(%{a: 1, b: 2, c: 3})
1

iex> :b |> canonical_key!(%{a: :p, b: :q, c: :r})
:q

iex> :x |> canonical_key!(%{a: 1, b: 2, c: 3})
** (KeyError) key :x not found in: %{a: 1, b: 2, c: 3}
Link to this function canonical_keys(keys, dict) View Source
canonical_keys(alias_keys(), any()) ::
  {:ok, alias_keys()} |
  {:error, error()}

canonical_keys/2 takes a key list and key alias dict and replaces each key with its canonical value from the dictionary, returning {:ok, canonical_keys}.

If there are any unknown keys {:error, error}, where error is a KeyError, will be returned.

Examples

iex> [:a, :b, :c] |> canonical_keys(%{a: :p, b: :q, c: :r})
{:ok, [:p,:q,:r]}

iex> [:a, :b, :c] |> canonical_keys(%{a: 1, b: 2, c: 3})
{:ok, [1,2,3]}

iex> [:a, :x, :b, :y, :c, :z] |> canonical_keys(%{a: 1, b: 2, c: 3})
{:error, %KeyError{key: [:x, :y, :z], term: %{a: 1, b: 2, c: 3}}}
Link to this function canonical_keys!(keys, dict) View Source
canonical_keys!(alias_keys(), dict()) :: alias_keys() | no_return()

canonical_keys!/2 calls canonical_keys/2 and if the result is {:ok, canonical_keys} returns canonical_keys.

Examples

iex> [:a, :b, :c] |> canonical_keys!(%{a: :p, b: :q, c: :r})
[:p,:q,:r]

iex> [:a, :b, :c] |> canonical_keys!(%{a: 1, b: 2, c: 3})
[1,2,3]

iex> [:a, :x, :b, :y, :c, :z] |> canonical_keys!(%{a: 1, b: 2, c: 3})
** (KeyError) key [:x, :y, :z] not found in: %{a: 1, b: 2, c: 3}
Link to this function list_wrap_flat_just(value) View Source
list_wrap_flat_just(any()) :: [any()]

list_wrap_flat_just/1 wraps a value (if not already a list), flattens and removes nils at the first / top level.

Examples

iex> [{:a, 1}, nil, [{:b1, 12}, nil, {:b2, [nil, 22, nil]}], nil, {:c, 3}] |> list_wrap_flat_just
[a: 1, b1: 12, b2: [nil, 22, nil], c: 3]

iex> [[[nil, 42, nil]]] |> list_wrap_flat_just
[42]
Link to this function list_wrap_flat_just_uniq(value) View Source
list_wrap_flat_just_uniq(any()) :: [any()]

list_wrap_flat_just_uniq/1 wraps a value (if not already a list), flattens, removes nils at the first / top level, and deletes duplicates (using Enum.uniq/1)

Examples

iex> [{:a, 1}, nil, [{:b1, 12}, nil, {:b2, [nil, 22, nil]}], nil, {:c, 3}, {:a, 1}, {:b1, 12}] |> list_wrap_flat_just_uniq
[a: 1, b1: 12, b2: [nil, 22, nil], c: 3]

iex> [nil, [42, [42, 42, nil]], 42] |> list_wrap_flat_just_uniq
[42]
Link to this function maybe_canon_keys(keys, dict) View Source
maybe_canon_keys(alias_keys(), dict()) :: alias_keys()

maybe_canon_keys/2 takes a key list together with a lookup dictionary and, if the key is in the dictionary, replaces it with its value. Unknown keys are passed through unchanged.

Examples

iex> [:a, :b, :c] |> maybe_canon_keys(%{a: 1, b: 2, c: 3})
[1, 2, 3]

iex> [:x, :a] |> maybe_canon_keys(%{a: 1, b: 2, c: 3})
[:x, 1]
Link to this function opts_avoir_keys(opts, keys) View Source
opts_avoir_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_avoir_keys/2 takes an opts and a key spec.

If all of the keys are present in the opts, its returns {:ok, opts}.

If there are any missing keys, {:error, error}, where error is a KeyError, will be returned.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys([:a, :b, :c])
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys(%{a: 1, b: 2, c: 3})
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys([:a, :b, :d, :a])
{:error, %KeyError{key: :d, term: [a: 1, b: 2, c: 3]}}

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys(%{x: nil, y: nil, z: nil})
{:error, %KeyError{key: [:x, :y, :z], term: [a: 1, b: 2, c: 3]}}
Link to this function opts_avoir_keys!(opts, keys) View Source
opts_avoir_keys!(any(), any()) :: opts() | no_return()

opts_avoir_keys!/2 calls opts_avoir_keys/2 and if the result is {:ok, opts}, returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys!([:a, :b, :c])
[a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys!(%{a: 1, b: 2, c: 3})
[a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys!([:a, :b, :d, :a])
** (KeyError) key :d not found in: [a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys!(%{x: nil, y: nil, z: nil})
** (KeyError) key [:x, :y, :z] not found in: [a: 1, b: 2, c: 3]
Link to this function opts_avoir_keys?(opts, keys) View Source
opts_avoir_keys?(any(), any()) :: true | false

opts_avoir_keys?/2 calls opts_avoir_keys/2 and if the result is {:ok, _}, returns true, else false.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys?([:a, :b, :c])
true

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys?(%{a: 1, b: 2, c: 3})
true

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys?([:a, :b, :d, :a])
false

iex> [a: 1, b: 2, c: 3] |> opts_avoir_keys?(%{x: nil, y: nil, z: nil})
false
Link to this function opts_canon_keys(opts, dict) View Source
opts_canon_keys(opts(), opts()) ::
  {:ok, opts()} |
  {:error, {opts(), opts()}}
opts_canon_keys(opts(), dict()) ::
  {:ok, opts()} |
  {:error, {opts(), opts()}}

opts_canon_keys/2 takes an opts, together with either a dictionary (map) or (keyword) list of aliases.

If a dictionary is provided, each key in the opts is replaced with its (canonical) value from the dictionary, returning {:ok, transformed_opts}.

If a (keyword) list of aliases is provided, the aliases are first converted into a dictionary by opts_create_aliases_dict/1 and the dictionary used as described above.

If there are any unknown keys, {:error, {known_opts, unknown_opts}} is returned.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_canon_keys(%{a: :x, b: :y, c: :z})
{:ok, [x: 1, y: 2, z: 3]}

iex> [a: 11, p: 1, b: 22, q: 2, c: 33, r: 3] |> opts_canon_keys(%{a: :x, b: :y, c: :z})
{:error, {[x: 11, y: 22, z: 33], [p: 1, q: 2, r: 3]}}

iex> [a: 1, b: 2, c: 3] |> opts_canon_keys([a_canon: :a, b_canon: [:b], c_canon: [:c, :cc]])
{:ok, [a_canon: 1, b_canon: 2, c_canon: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_canon_keys([a_canon: :a, b_canon: nil, c_canon: [:c, :cc]])
{:error, {[a_canon: 1, c_canon: 3], [b: 2]}}
Link to this function opts_canon_keys!(opts, dict) View Source
opts_canon_keys!(opts(), dict()) :: opts() | no_return()

opts_canon_keys!/2 takes an opts, together with a lookup dictionary and replaces each key with its canonical value from the dictionary. Unknown keys raise a KeyError.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_canon_keys!(%{a: :x, b: :y, c: :z})
[x: 1, y: 2, z: 3]

iex> [x: 1, y: 3, z: 3] |> opts_canon_keys!(%{a: 1, b: 2, c: 3})
** (KeyError) key :x not found in: %{a: 1, b: 2, c: 3}
Link to this function opts_canonical_keys(opts, dict) View Source
opts_canonical_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_canonical_keys/2 takes a derivable opts, together with a key alias dict.

Each key in the opts is replaced with its (canonical) value from the dictionary, returning {:ok, canon_opts}.

If there are any unknown keys, {:error, error}, where error is a KeyError, will be returned.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_canonical_keys(%{a: :x, b: :y, c: :z})
{:ok, [x: 1, y: 2, z: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_canonical_keys([a: :x, b: :y, c: :z])
{:ok, [x: 1, y: 2, z: 3]}

iex> [a: 11, p: 1, b: 22, q: 2, c: 33, r: 3] |> opts_canonical_keys(%{a: :x, b: :y, c: :z})
{:error, %KeyError{key: [:p, :q, :r], term: %{a: :x, b: :y, c: :z}}}

iex> [a: 1, b: 2, c: 3] |> opts_canonical_keys([a_canon: :a, b_canon: [:b], c_canon: [:c, :cc]])
{:error, %ArgumentError{message: "expected valid key alias dictionary; got: %{a_canon: :a, b_canon: [:b], c_canon: [:c, :cc]}"}}
Link to this function opts_canonical_keys!(opts, dict) View Source
opts_canonical_keys!(any(), any()) :: opts() | no_return()

opts_canonical_keys!/2 calls opts_canonical_keys/2 and if the result is {:ok, opts} returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_canonical_keys!(%{a: :x, b: :y, c: :z})
[x: 1, y: 2, z: 3]

iex> [a: 1, b: 2, c: 3] |> opts_canonical_keys!([a: :x, b: :y, c: :z])
[x: 1, y: 2, z: 3]

iex> [x: 1, y: 3, z: 3] |> opts_canonical_keys!(%{a: 1, b: 2, c: 3})
** (ArgumentError) expected valid key alias dictionary; got: %{a: 1, b: 2, c: 3}
Link to this function opts_create_aliases_dict(aliases) View Source
opts_create_aliases_dict(aliases_kvs()) :: aliases_dict()

opts_create_aliases_dict/1 does the same job as opts_create_aliases_tuples/1 but returns a key alias dict.

Examples

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_create_aliases_dict
%{a: :a, b: :b, b1: :b, c: :c, c1: :c, c2: :c, c3: :c}
Link to this function opts_create_aliases_tuples(aliases) View Source
opts_create_aliases_tuples(aliases_kvs()) :: aliases_tuples()

opts_create_aliases_tuples/1 takes an opts where the keys are the canonical key names, and their values are zero (nil), one or more aliases for the canonical key.

A Keyword is returned where each key is an alias and its value the canonical key.

The canonical key also has an entry for itself with the same value.

Examples

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_create_aliases_tuples
[a: :a, b: :b, b1: :b, c: :c, c1: :c, c2: :c, c3: :c]
Link to this function opts_create_defstruct(struct_kvs, defaults_map \\ %{}) View Source
opts_create_defstruct(opts(), defaults_map()) :: opts()

opts_create_defstruct/2 takes an opts, together with a defaults map, and returns an opts where each value if the value of the key in the defaults map (with default nil).

opts_create_defstruct/2 creates an argument suitable for use with Kernel.defstruct/1

The defaults map must contain only keys that are also in the opts list; any unknown keys will raise a KeyError.

Examples

iex> [a: 1, b: :two, c: "tre", d: nil] |> opts_create_defstruct(%{a: 42, b: "two"})
[a: 42, b: "two", c: nil, d: nil]

iex> [a: 1, b: :two, c: "tre", d: nil] |> opts_create_defstruct(%{a: 42, b: "two", x: 1})
** (KeyError) key [:x] not found in: [a: 1, b: :two, c: "tre", d: nil]
Link to this function opts_crue_defstruct(struct_kvs, defaults_map \\ %{}) View Source
opts_crue_defstruct(opts(), defaults_map()) ::
  {:ok, opts()} |
  {:error, error()}

opts_crue_defstruct/2 takes a derivable opts, together with a defaults map, and returns {:ok, opts} where each value is the value of the key in the defaults map (with default nil).

opts_crue_defstruct/2 creates an argument suitable for use with Kernel.defstruct/1

The defaults map must contain only keys that are also in the opts list; any unknown keys will cause {:error, error}, where error is a KeyError, to be returned.

Examples

iex> [a: 1, b: :two, c: "tre", d: nil] |> opts_crue_defstruct(%{a: 42, b: "two"})
{:ok, [a: 42, b: "two", c: nil, d: nil]}

iex> [a: 1, b: :two, c: "tre", d: nil] |> opts_crue_defstruct(%{a: 42, b: "two", x: 1})
{:error, %KeyError{key: :x, term: [a: 1, b: :two, c: "tre", d: nil]}}
Link to this function opts_crue_defstruct!(struct_kvs, defaults_map \\ %{}) View Source
opts_crue_defstruct!(opts(), defaults_map()) :: opts() | no_return()

opts_crue_defstruct!/2 calls opts_crue_defstruct/2 and if the result is {:ok, opts} returns opts.

Examples

iex> [a: 1, b: :two, c: "tre", d: nil] |> opts_crue_defstruct!(%{a: 42, b: "two"})
[a: 42, b: "two", c: nil, d: nil]

iex> [a: 1, b: :two, c: "tre", d: nil] |> opts_crue_defstruct!(%{a: 42, b: "two", x: 1})
** (KeyError) key :x not found in: [a: 1, b: :two, c: "tre", d: nil]
Link to this function opts_drop_keys!(opts, keys \\ []) View Source
opts_drop_keys!(opts(), keys()) :: opts()

opts_drop_keys!/1 takes an opts, together with a key list and returns the opts without the supplied keys.

It any of the keys are not found, raises a KeyError citing the missing keys.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_drop_keys!([:b])
[a: 1, c: 3]

iex> [a: 11, b: 21, c: 3, b: 22, a: 12] |> opts_drop_keys!([:b])
[a: 11, c: 3, a: 12]

iex> [a: 1, b: 2, c: 3] |> opts_drop_keys!([:d, :a])
** (KeyError) key [:d] not found in: [a: 1, b: 2, c: 3]
Link to this function opts_fetch_key_values(opts, key, indicies \\ nil) View Source

opts_fetch_key_values/2 takes a derivable opts and a key and returns the values of the key as {:ok, values} where values will be a list.

One of more indices can be provided to select the values at specific indices; the default is to return all values from Keyword.get_values/2.

Note indices must be relative to the result of Keyword.get_values/2 not the indices of the original opts

Values are returned in the same order as the indices. Indices may be repeated. Indices are validated; asking for an unknown/impossible index will cause an error.

Examples

The default is to return all the values for a key i.e same as Keyword.get_values/2:

iex> [a: 1, b: 2, c: 3] |> opts_fetch_key_values(:a)
{:ok, [1]}

This examples show multiple values being returned:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a)
{:ok, [11, 12, 13]}

Here the last value for the key is returned:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, -1)
{:ok, [13]}

Here only the first value is wanted:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, 0)
{:ok, [11]}

Values at different indices:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, [1,-1])
{:ok, [12, 13]}

Note order of the values is same order as the indices:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, [-2,0,-1])
{:ok, [12, 11, 13]}

The same index/indices can be repeated:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, [-2,0,-2,-1,0])
{:ok, [12, 11, 12, 13, 11]}

Indices are validated:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, 99)
{:error, %ArgumentError{message: "index invalid; got: 99"}}

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values(:a, :not_an_index)
{:error, %ArgumentError{message: "index invalid; got: :not_an_index"}}
Link to this function opts_fetch_key_values!(opts, key, indices \\ nil) View Source
opts_fetch_key_values!(any(), any(), any()) :: list() | no_return()

opts_fetch_key_values!/2 takes a derivable opts and a key and returns the values of the key as {:ok, values}.

One of more indices can be provided to select the values at specific indices; the default is to return all values from Keyword.get_values/2.

Note indices must be relative to the result of Keyword.get_values/2 not the indices of the original opts

Values are returned in the order they are given in the indices. Indices may be repeated.

Examples

The default is to return all the values for a key:

iex> [a: 1, b: 2, c: 3] |> opts_fetch_key_values!(:a)
[1]

This examples show multiple values being returned:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a)
[11, 12, 13]

Here the last value for the key is returned:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a, -1)
[13]

Here the first value is wanted:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a, 0)
[11]

Values at different indices:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a, [1,-1])
[12, 13]

Note order of the values is same as order of the indices

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a, [-2,0,-1])
[12, 11, 13]

The same index/indices can be requested more than once:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a, [-2,0,-2,-1,0])
[12, 11, 12, 13, 11]

Indices are validated:

iex> [a: 11, b: 2, a: 12, c: 3, a: 13] |> opts_fetch_key_values!(:a, :not_an_index)
** (ArgumentError) index invalid; got: :not_an_index
Link to this function opts_filter(opts, fun_pred) View Source
opts_filter(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_filter/2 takes a derivable opts, together with a tuple predicate and returns {:ok, opts} where opts has all the 2tuples the tuple predicate return true for.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_filter(&(&1))
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_filter(
...>   fn
...>   {:a,_} -> true
...>   _ -> false
...>   end)
{:ok, [a: 1]}

iex> %{a: 1, b: 2, c: 3} |> opts_filter(
...>   fn
...>   {:a,_} -> false
...>   _ -> true
...>   end)
{:ok, [b: 2, c: 3]}

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_filter(:not_a_function)
...> match?(%ArgumentError{message: "expected valid tuple predicate; got: :not_a_function"}, error)
true

iex> {:error, error} = :not_opts |> opts_filter(&(&1))
...> match?(%ArgumentError{message: "expected valid derivable opts; got: :not_opts"}, error)
true
Link to this function opts_filter!(opts, dict) View Source
opts_filter!(any(), any()) :: opts() | no_return()

opts_filter!/2 calls opts_filter/2 and if the result is {:ok, opts} returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_filter!(&(&1))
[a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_filter!(
...>   fn
...>   {:a,_} -> true
...>   _ -> false
...>   end)
[a: 1]

iex> %{a: 1, b: 2, c: 3} |> opts_filter!(
...>   fn
...>   {:a,_} -> false
...>   _ -> true
...>   end)
[b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_filter!(:not_a_function)
** (ArgumentError) expected valid tuple predicate; got: :not_a_function

iex> :not_opts |> opts_filter!(&(&1))
** (ArgumentError) expected valid derivable opts; got: :not_opts
Link to this function opts_filter_keys(opts, keys) View Source
opts_filter_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_filter_keys/2 takes a derivable opts and a key spec and returns {:ok, opts} where opts has all keys from the original derivable opts that appear in the key spec.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys([:a, :b, :c])
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys([b: :want_b, c: :and_c])
{:ok, [b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys(%{a: 42, b: nil})
{:ok, [a: 1, b: 2]}

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys(:not_a_key_spec)
{:error, %ArgumentError{message: "expected enum; got: :not_a_key_spec"}}

iex> :not_opts |> opts_filter_keys([:a, :b, :c])
{:error, %ArgumentError{message: "expected valid derivable opts; got: :not_opts"}}
Link to this function opts_filter_keys!(opts, keys) View Source
opts_filter_keys!(any(), any()) :: opts() | no_return()

opts_filter_keys!/2 calls opts_filter_keys/2 and if the result is {:ok, opts}, returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys!([:a, :b, :c])
[a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys!([b: :want_b, c: :and_c])
[b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys!(%{a: 42, b: nil})
[a: 1, b: 2]

iex> [a: 1, b: 2, c: 3] |> opts_filter_keys!(:not_a_key_spec)
** (ArgumentError) expected enum; got: :not_a_key_spec

iex> :not_opts |> opts_filter_keys!([:a, :b, :c])
** (ArgumentError) expected valid derivable opts; got: :not_opts
Link to this function opts_has_keys(opts, keys_or_dict) View Source
opts_has_keys(opts(), dict()) ::
  {:ok, opts()} |
  {:error, {opts(), opts()}}
opts_has_keys(opts(), keys()) ::
  {:ok, opts()} |
  {:error, {opts(), opts()}}

opts_has_keys/2 takes an opts, together with a list or dictionary (map) of wanted keys.

If all of the keys are present in the opts, its returns {:ok, opts}.

If there are any missing keys, {:error, {present_opts, missing_keys}} is returned, where the present_opts include only the tuples for the wanted keys (i.e. result of Keyword.take/2 for the wanted keys).

Examples

iex> [a: 1, b: 2, c: 3] |> opts_has_keys([:a, :b, :c])
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_has_keys(%{a: 1, b: 2, c: 3})
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_has_keys([:a, :b, :d, :a])
{:error, {[a: 1, b: 2], [:d]}}

iex> [a: 1, b: 2, c: 3] |> opts_has_keys(%{x: nil, y: nil, z: nil})
{:error, {[], [:x, :y, :z]}}
Link to this function opts_has_keys!(opts, keys) View Source
opts_has_keys!(opts(), dict()) :: opts() | no_return()
opts_has_keys!(opts(), keys()) :: opts() | no_return()

opts_has_keys!/2 calls opts_has_keys/2 and if the result is {:ok, opts}, returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_has_keys!([:a, :b, :c])
[a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_has_keys!(%{a: 1, b: 2, c: 3})
[a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_has_keys!([:a, :b, :d, :a])
** (KeyError) key [:d] not found in: [a: 1, b: 2, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_has_keys!(%{x: nil, y: nil, z: nil})
** (KeyError) key [:x, :y, :z] not found in: [a: 1, b: 2, c: 3]
Link to this function opts_has_keys?(opts, keys) View Source
opts_has_keys?(opts(), dict()) :: true | false
opts_has_keys?(opts(), keys()) :: true | false

opts_has_keys?/2 calls opts_has_keys/2 and if the result is {:ok, _}, returns true, else false.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_has_keys?([:a, :b, :c])
true

iex> [a: 1, b: 2, c: 3] |> opts_has_keys?(%{a: 1, b: 2, c: 3})
true

iex> [a: 1, b: 2, c: 3] |> opts_has_keys?([:a, :b, :d, :a])
false

iex> [a: 1, b: 2, c: 3] |> opts_has_keys?(%{x: nil, y: nil, z: nil})
false
Link to this function opts_normalise(value) View Source
opts_normalise(any()) :: {:ok, opts()} | {:error, error()}

opts_normalise/ expects a derivable opts and returns {:ok, opts}.

Any other argument causes {:error, error} to be returned.

Examples

iex> [] |> opts_normalise
{:ok, []}

iex> %{a: 1, b: 2, c: 3} |> opts_normalise
{:ok, [a: 1, b: 2, c: 3]}

iex> %{"a" => 1, :b => 2, :c => 3} |> opts_normalise
{:error, %KeyError{key: "a", term: %{:b => 2, :c => 3, "a" => 1}}}

iex> 42 |> opts_normalise
{:error, %ArgumentError{message: "expected valid derivable opts; got: 42"}}

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_normalise
{:ok, [a: nil, b: [:b1], c: [:c1, :c2, :c3]]}
Link to this function opts_normalise!(opts) View Source
opts_normalise!(any()) :: opts() | no_return()

opts_normalise!/1 calls opts_normalise/1 and if the result is {:ok, opts} returns opts.

Examples

iex> [] |> opts_normalise!
[]

iex> %{a: 1, b: 2, c: 3} |> opts_normalise!
[a: 1, b: 2, c: 3]

iex> %{"a" => 1, :b => 2, :c => 3} |> opts_normalise!
** (KeyError) key "a" not found in: %{:b => 2, :c => 3, "a" => 1}

iex> 42 |> opts_normalise!
** (ArgumentError) expected valid derivable opts; got: 42

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_normalise!
[a: nil, b: [:b1], c: [:c1, :c2, :c3]]
Link to this function opts_normalise_map(value) View Source
opts_normalise_map(any()) :: {:ok, opts()} | {:error, error()}

opts_normalise_map/ expects a derivable opts as argument.

If the argument is a Map, with Atom keys, it returns {:ok, argument} directly.

If the argument is a Keyword, with Atom keys, it returns {:ok, argument |> Enum.into(%{})}.

Any other argument causes {:error, error} to be returned.

Examples

iex> [] |> opts_normalise_map
{:ok, %{}}

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_normalise_map
{:ok, %{a: nil, b: [:b1], c: [:c1, :c2, :c3]}}

iex> %{a: 1, b: 2, c: 3} |> opts_normalise_map
{:ok, %{a: 1, b: 2, c: 3}}

iex> %{"a" => 1, :b => 2, :c => 3} |> opts_normalise_map
{:error, %KeyError{key: ["a"], term: %{:b => 2, :c => 3, "a" => 1}}}

iex> 42 |> opts_normalise_map
{:error, %ArgumentError{message: "expected valid derivable opts; got: 42"}}
Link to this function opts_normalise_map!(opts) View Source
opts_normalise_map!(any()) :: opts() | no_return()

opts_normalise_map!/1 call opts_normalise_map/1 and if the result is {:ok, map} returns map.

Examples

iex> [] |> opts_normalise_map!
%{}

iex> [a: 1, b: 2, c: 3] |> opts_normalise_map!
%{a: 1, b: 2, c: 3}

iex> %{a: 1, b: 2, c: 3} |> opts_normalise_map!
%{a: 1, b: 2, c: 3}

iex> %{"a" => 1, :b => 2, :c => 3} |> opts_normalise_map!
** (KeyError) key ["a"] not found in: %{:b => 2, :c => 3, "a" => 1}

iex> 42 |> opts_normalise_map!
** (ArgumentError) expected valid derivable opts; got: 42
Link to this function opts_predicate(opts, fun_pred) View Source
opts_predicate(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_predicate/2 takes a derivable opts, together with a tuple predicate and returns {:ok, opts} if all the 2tuples pass the tuple predicate.

If any of the opts fail the tuple predicate, {:error, error} is returned where error will be a KeyError whose key field contains all the keys that failed.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_predicate(&(&1))
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_predicate(fn {_k,v} -> v |> is_integer end)
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_predicate(
...>   fn
...>   {:a,_} -> true
...>   _ -> false
...>   end)
{:error, %KeyError{key: [:b, :c], term: [a: 1, b: 2, c: 3]}}

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_predicate(:not_a_function)
...> match?(%ArgumentError{message: "expected valid tuple predicate; got: :not_a_function"}, error)
true

iex> {:error, error} = :not_opts |> opts_predicate(&(&1))
...> match?(%ArgumentError{message: "expected valid derivable opts; got: :not_opts"}, error)
true
Link to this function opts_predicate!(opts, dict) View Source
opts_predicate!(any(), any()) :: opts() | no_return()

opts_predicate!/2 calls opts_predicate/2 and if the result is {:ok, opts} returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_predicate(&(&1))
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_predicate(fn {_k,v} -> v |> is_integer end)
{:ok, [a: 1, b: 2, c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_predicate(
...>   fn
...>   {:a,_} -> true
...>   _ -> false
...>   end)
{:error, %KeyError{key: [:b, :c], term: [a: 1, b: 2, c: 3]}}

iex> [a: 1, b: 2, c: 3] |> opts_predicate!(:not_a_function)
** (ArgumentError) expected valid tuple predicate; got: :not_a_function

iex> :not_opts |> opts_predicate!(&(&1))
** (ArgumentError) expected valid derivable opts; got: :not_opts
Link to this function opts_reject(opts, fun_pred) View Source
opts_reject(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_reject/2 takes a derivable opts, together with a tuple predicate and returns {:ok, opts} where opts has all the 2tuples the tuple predicate returns false for.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_reject(&(&1))
{:ok, []}

iex> [a: 1, b: 2, c: 3] |> opts_reject(
...>   fn
...>   {:a,_} -> true
...>   _ -> false
...>   end)
{:ok, [b: 2, c: 3]}

iex> %{a: 1, b: 2, c: 3} |> opts_reject(
...>   fn
...>   {:a,_} -> false
...>   _ -> true
...>   end)
{:ok, [a: 1]}

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_reject(:not_a_function)
...> match?(%ArgumentError{message: "expected valid tuple predicate; got: :not_a_function"}, error)
true

iex> {:error, error} = :not_opts |> opts_reject(&(&1))
...> match?(%ArgumentError{message: "expected valid derivable opts; got: :not_opts"}, error)
true
Link to this function opts_reject!(opts, dict) View Source
opts_reject!(any(), any()) :: opts() | no_return()

opts_reject!/2 calls opts_reject/2 and if the result is {:ok, opts} returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_reject!(&(&1))
[]

iex> [a: 1, b: 2, c: 3] |> opts_reject!(
...>   fn
...>   {:a,_} -> true
...>   _ -> false
...>   end)
[b: 2, c: 3]

iex> %{a: 1, b: 2, c: 3} |> opts_reject!(
...>   fn
...>   {:a,_} -> false
...>   _ -> true
...>   end)
[a: 1]

iex> [a: 1, b: 2, c: 3] |> opts_reject!(:not_a_function)
** (ArgumentError) expected valid tuple predicate; got: :not_a_function

iex> :not_opts |> opts_reject!(&(&1))
** (ArgumentError) expected valid derivable opts; got: :not_opts
Link to this function opts_reject_keys(opts, keys) View Source
opts_reject_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_reject_keys/2 takes a derivable opts and a key spec and returns {:ok, opts} where opts has all keys from the original derivable opts that do not appear in the key spec.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys([:a, :b, :c])
{:ok, []}

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys([b: "b value", c: :dont_want_this_key])
{:ok, [a: 1]}

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys(%{a: nil, b: nil})
{:ok, [c: 3]}

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys(:not_a_key_spec)
{:error, %ArgumentError{message: "expected enum; got: :not_a_key_spec"}}

iex> :not_opts |> opts_reject_keys([:a, :b, :c])
{:error, %ArgumentError{message: "expected valid derivable opts; got: :not_opts"}}
Link to this function opts_reject_keys!(opts, keys) View Source
opts_reject_keys!(any(), any()) :: opts() | no_return()

opts_reject_keys!/2 calls opts_reject_keys/2 and if the result is {:ok, opts}, returns opts.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys!([:a, :b, :c])
[]

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys!([b: "b value", c: :dont_want_this_key])
[a: 1]

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys!(%{a: nil, b: nil})
[c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_reject_keys!(:not_a_key_spec)
** (ArgumentError) expected enum; got: :not_a_key_spec

iex> :not_opts |> opts_reject_keys!([:a, :b, :c])
** (ArgumentError) expected valid derivable opts; got: :not_opts
Link to this function opts_sort_keys(opts, keys \\ []) View Source
opts_sort_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_sort_keys/ takes a derivable opts, together with a list of sort keys, and returns the opts sorted in the sort keys order. Duplicate keys follow one after another.

Any keys found but not given in the sort keys follow the sorted keys in the returned opts.

Any key in the sort list not found in the opts is ignored.

Examples

iex> [a: 1, b: 2, c: 3, d: 4] |> opts_sort_keys
[a: 1, b: 2, c: 3, d: 4]

iex> [a: 1, b: 2, c: 3, d: 4] |> opts_sort_keys([:c, :a])
[c: 3, a: 1,  b: 2, d: 4]

iex> [] |> opts_sort_keys([:c, :a])
[]

iex> [a: 11, b: 2, c: 3, a: 12, d: 4] |> opts_sort_keys([:c, :a])
[c: 3, a: 11, a: 12, b: 2, d: 4]

iex> [a: 11, b: 21, c: 3, a: 12, d: 4, b: 22] |> opts_sort_keys([:d, :x, :b, :z])
[d: 4, b: 21, b: 22, a: 11, c: 3, a: 12]
Link to this function opts_take_keys!(opts, keys \\ []) View Source
opts_take_keys!(opts(), keys()) :: opts()

opts_take_keys!/1 takes an opts, together with a key list and returns the opts with just the supplied keys.

It any of the keys are not found, raises a KeyError citing the missing keys.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_take_keys!([:c, :a])
[a: 1, c: 3]

iex> [a: 1, b: 2, c: 3] |> opts_take_keys!([:d, :a])
** (KeyError) key [:d] not found in: [a: 1, b: 2, c: 3]
Link to this function opts_validate(value) View Source
opts_validate(any()) :: {:ok, opts()} | {:error, error()}

opts_validate/1 returns {:ok, opts} if the argument is an opts.

Any other argument causes {:error, error} to be returned.

Examples

iex> [] |> opts_validate
{:ok, []}

iex> %{a: 1, b: 2, c: 3} |> opts_validate
{:error, %ArgumentError{message: "validate opts failed; got: %{a: 1, b: 2, c: 3}"}}

iex> %{"a" => 1, :b => 2, :c => 3} |> opts_validate
{:error, %ArgumentError{message: "validate opts failed; got: %{:b => 2, :c => 3, \"a\" => 1}"}}

iex> 42 |> opts_validate
{:error, %ArgumentError{message: "validate opts failed; got: 42"}}

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_validate
{:ok, [a: nil, b: [:b1], c: [:c1, :c2, :c3]]}
Link to this function opts_validate!(opts) View Source
opts_validate!(opts()) :: opts() | no_return()

opts_validate!/1 calls opts_validate/1 and, if the result is {:ok, opts}, returns opts.

Examples

iex> [] |> opts_validate!
[]

iex> %{a: 1, b: 2, c: 3} |> opts_validate!
** (ArgumentError) validate opts failed; got: %{a: 1, b: 2, c: 3}

iex> %{"a" => 1, :b => 2, :c => 3} |> opts_validate!
** (ArgumentError) validate opts failed; got: %{:b => 2, :c => 3, "a" => 1}

iex> 42 |> opts_validate!
** (ArgumentError) validate opts failed; got: 42

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opts_validate!
[a: nil, b: [:b1], c: [:c1, :c2, :c3]]