plymio_fontais v0.2.0 Plymio.Fontais.Option View Source

Functions for Managing Keyword Options (“opts”)

See Plymio.Fontais for overview and other documentation terms.

Documentation Terms

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.

Link to this section Summary

Functions

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_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}

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

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_drop/3 take a derivable opts, key and delete all occurences of the key returning {ok, opts}

opts_fetch/2 take a derivable opts and key and and returns the last value for the key (or default) as {:ok, value}

opts_get/3 take a derivable opts, key and default and returns the last value for the key (or default) as {:ok, value_or_default}

opts_get_values/3 take a derivable opts, key and default and, if the derived opts has the key, returns the values (Keyword.get_values/21)

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

opts_merge/ takes one or more derivable opts, merges them and returns {:ok, opts}

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

opts_put/3 take a derivable opts, key and a value and appends the {key,value} tuple returnsing {:ok, opts}

opts_put_new/3 take a derivable opts, key and a value

opts_reduce/3 take a derivable opts, realises the derived opts, and calls Keyword.new/1 to take the last {key, value} tuple for the same key, returning {:ok, reduced_opts}

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

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

opzioni_flatten/1 takes a value, calls opzioni_normalise/1 and then merges all the individual opts into a single opts

opzioni_merge/ takes one or more opzioni, normalises each one and merges them to return {:ok, opzioni}

opzioni_normalise/1 takes a value tries to normalise it into an opzioni, returning {:ok, opzioni}

opzioni_validate/1 takes a value and validates it is an opzioni, returning {:ok, opzioni}

Link to this section Types

Link to this section Functions

Link to this function canonical_key(key, dict) View Source
canonical_key(any(), any()) :: {:ok, 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_keys(keys, dict) View Source
canonical_keys(any(), any()) :: {:ok, 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 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_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_drop(opts, keys) View Source
opts_drop(any(), any()) :: {:ok, opts()} | {:error, error()}

opts_drop/3 take a derivable opts, key and delete all occurences of the key returning {ok, opts}.

It essentially wraps Keyword.delete/2.

Examples

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

iex> [a: 11, b: 21, c: 31, a: 12, b: 22, c: 32, a: 13, b: 23, c: 33] |> opts_drop([:a, :c])
{:ok, [b: 21, b: 22, b: 23]}

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_drop([:b, "a"])
...> error |> Exception.message
"bad key \"a\" for: [:b, \"a\"]"

iex> {:error, error} = 42 |> opts_drop(:a)
...> error |> Exception.message
"opts not derivable, got: 42"

iex> {:error, error} = [{:a, 1}, {:b, 2}, {"c", 3}] |> opts_drop(:a)
...> error |> Exception.message
"opts not derivable, got: [{:a, 1}, {:b, 2}, {\"c\", 3}]"
Link to this function opts_fetch(opts, key) View Source
opts_fetch(any(), any()) :: {:ok, any()} | {:error, error()}

opts_fetch/2 take a derivable opts and key and and returns the last value for the key (or default) as {:ok, value}.

Note this is different to Keyword.fetch/2 that returns the first value.

Examples

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

iex> [a: 11, b: 21, c: 31, a: 12, b: 22, c: 32, a: 13, b: 23, c: 33] |> opts_fetch(:c)
{:ok, 33}

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_fetch(:d)
...> error |> Exception.message
"key :d not found in: [a: 1, b: 2, c: 3]"

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_fetch("a")
...> error |> Exception.message
"key invalid, got: a"

iex> {:error, error} = 42 |> opts_fetch(:a)
...> error |> Exception.message
"opts not derivable, got: 42"

iex> {:error, error} = [{:a, 1}, {:b, 2}, {"c", 3}] |> opts_fetch(:a)
...> error |> Exception.message
"opts not derivable, got: [{:a, 1}, {:b, 2}, {\"c\", 3}]"
Link to this function opts_get(opts, key, default \\ nil) View Source
opts_get(any(), any(), any()) :: {:ok, any()} | {:error, error()}

opts_get/3 take a derivable opts, key and default and returns the last value for the key (or default) as {:ok, value_or_default}.

Note this is different to Keyword.get/3 that returns the first value.

Examples

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

iex> [a: 11, b: 21, c: 31, a: 12, b: 22, c: 32, a: 13, b: 23, c: 33] |> opts_get(:c)
{:ok, 33}

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

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_get("a")
...> error |> Exception.message
"key invalid, got: a"

iex> {:error, error} = 42 |> opts_get(:a)
...> error |> Exception.message
"opts not derivable, got: 42"

iex> {:error, error} = [{:a, 1}, {:b, 2}, {"c", 3}] |> opts_get(:a)
...> error |> Exception.message
"opts not derivable, got: [{:a, 1}, {:b, 2}, {\"c\", 3}]"
Link to this function opts_get_values(opts, key, default \\ nil) View Source
opts_get_values(any(), any(), any()) :: {:ok, list()} | {:error, error()}

opts_get_values/3 take a derivable opts, key and default and, if the derived opts has the key, returns the values (Keyword.get_values/21).

Otherwise the “listified” (List.wrap/1) default is returned.

Examples

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

iex> [a: 11, b: 21, c: 31, a: 12, b: 22, c: 32, a: 13, b: 23, c: 33] |> opts_get_values(:c)
{:ok, [31, 32, 33]}

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

iex> [a: 1, b: 2, c: 3] |> opts_get_values(:d, [41, 42, 43])
{:ok, [41, 42, 43]}

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_get_values("a")
...> error |> Exception.message
"key invalid, got: a"

iex> {:error, error} = 42 |> opts_get_values(:a)
...> error |> Exception.message
"opts not derivable, got: 42"
Link to this function opts_maybe_canonical_keys(opts, dict) View Source
opts_maybe_canonical_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

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

If an opts key exists in the dictionary, it is replaced with its (canonical) value. Otherwise the key is unchanged.

{:ok, opts} is returned.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_maybe_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_maybe_canonical_keys(%{a: :x, b: :y, c: :z})
{:ok, [x: 11, p: 1, y: 22, q: 2, z: 33, r: 3]}
Link to this function opts_merge(value) View Source
opts_merge(any()) :: {:ok, opts()} | {:error, error()}

opts_merge/ takes one or more derivable opts, merges them and returns {:ok, opts}.

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

Examples

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

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

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

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

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

iex> {:error, error} = [[d: 4], %{"a" => 1, :b => 2, :c => 3}] |> opts_merge
...> error |> Exception.message
"bad key \"a\" for: %{:b => 2, :c => 3, \"a\" => 1}"

iex> {:error, error} = 42 |> opts_merge
...> error |> Exception.message
"opts not derivable, got: 42"
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> {:error, error} = %{"a" => 1, :b => 2, :c => 3} |> opts_normalise
...> error |> Exception.message
"bad key \"a\" for: %{:b => 2, :c => 3, \"a\" => 1}"

iex> {:error, error} = 42 |> opts_normalise
...> error |> Exception.message
"opts not derivable, 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_put(opts, key, value) View Source
opts_put(any(), any(), any()) :: {:ok, any()} | {:error, error()}

opts_put/3 take a derivable opts, key and a value and appends the {key,value} tuple returnsing {:ok, opts}.

Note this is different to Keyword.put/2 which prepends the new {key,value} tuple and drops all the other for the same key.

Examples

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

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

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_put("a", 99)
...> error |> Exception.message
"key invalid, got: a"

iex> {:error, error} = 42 |> opts_put(:a, nil)
...> error |> Exception.message
"opts not derivable, got: 42"

iex> {:error, error} = [{:a, 1}, {:b, 2}, {"c", 3}] |> opts_put(:a, nil)
...> error |> Exception.message
"opts not derivable, got: [{:a, 1}, {:b, 2}, {\"c\", 3}]"
Link to this function opts_put_new(opts, key, value \\ nil) View Source
opts_put_new(any(), any(), any()) :: {:ok, any()} | {:error, error()}

opts_put_new/3 take a derivable opts, key and a value.

If the key already exsists in the derived opts, they are returned unchanged as {:ok, opts}.

Otherwise opts_put/3 is called to append the new {key,value}, again returning {:ok, opts}.

Examples

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

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

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opts_put_new("a", 99)
...> error |> Exception.message
"key invalid, got: a"

iex> {:error, error} = 42 |> opts_put_new(:a)
...> error |> Exception.message
"opts not derivable, got: 42"

iex> {:error, error} = [{:a, 1}, {:b, 2}, {"c", 3}] |> opts_put_new(:a)
...> error |> Exception.message
"opts not derivable, got: [{:a, 1}, {:b, 2}, {\"c\", 3}]"
Link to this function opts_reduce(opts \\ []) View Source
opts_reduce(any()) :: {:ok, opts()} | {:error, error()}

opts_reduce/3 take a derivable opts, realises the derived opts, and calls Keyword.new/1 to take the last {key, value} tuple for the same key, returning {:ok, reduced_opts}.

Examples

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

iex> {:ok, opts} = %{a: 1, b: 2, c: 3} |> opts_reduce
...> opts |> Enum.sort
[a: 1, b: 2, c: 3]

iex> [a: 11, b: 21, c: 31, a: 12, b: 22, c: 32, a: 13, b: 23, c: 33] |> opts_reduce
{:ok, [a: 13, b: 23, c: 33]}

iex> {:error, error} = 42 |> opts_reduce
...> error |> Exception.message
"opts not derivable, got: 42"

iex> {:error, error} = [{:a, 1}, {:b, 2}, {"c", 3}] |> opts_reduce
...> error |> Exception.message
"opts not derivable, got: [{:a, 1}, {:b, 2}, {\"c\", 3}]"
Link to this function opts_take_canonical_keys(opts, dict) View Source
opts_take_canonical_keys(any(), any()) :: {:ok, opts()} | {:error, error()}

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

It first calls opts_maybe_canonical_keys/2 to convert all known keys to their canonical values, and then takes only the canonical keys returning {:ok, opts}.

Examples

iex> [a: 1, b: 2, c: 3] |> opts_take_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_take_canonical_keys(%{a: :x, b: :y, c: :z})
{:ok, [x: 11, y: 22, z: 33]}
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: "opts invalid, got: %{a: 1, b: 2, c: 3}"}}

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

iex> 42 |> opts_validate
{:error, %ArgumentError{message: "opts invalid, 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 opzioni_flatten(opzioni \\ []) View Source
opzioni_flatten(any()) :: {:ok, opts()} | {:error, error()}

opzioni_flatten/1 takes a value, calls opzioni_normalise/1 and then merges all the individual opts into a single opts.

Examples

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

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

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

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

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

iex> {:ok, opts} = [[a: 1, b: 2, c: 3], %{x: 10, y: 11, z: 12}] |> opzioni_flatten
...> opts |> Enum.sort
[a: 1, b: 2, c: 3, x: 10, y: 11, z: 12]

iex> {:error, error} = %{"a" => 1, :b => 2, :c => 3} |> opzioni_flatten
...> error |> Exception.message
"bad key \"a\" for: %{:b => 2, :c => 3, \"a\" => 1}"

iex> {:error, error} = 42 |> opzioni_flatten
...> error |> Exception.message
"opzioni invalid, got: 42"

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opzioni_flatten
{:ok, [a: nil, b: [:b1], c: [:c1, :c2, :c3]]}
Link to this function opzioni_merge(opzioni) View Source
opzioni_merge(any()) :: {:ok, opzioni()} | {:error, error()}

opzioni_merge/ takes one or more opzioni, normalises each one and merges them to return {:ok, opzioni}.

Empty opts are removed.

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

Examples

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

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

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

iex> [[[a: 1], [b: 2]], [c: 3], [[d: 4]]] |> opzioni_merge
{:ok, [[a: 1], [b: 2], [c: 3], [d: 4]]}

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

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

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

iex> {:error, error} = [[d: 4], %{"a" => 1, :b => 2, :c => 3}] |> opzioni_merge
...> error |> Exception.message
"bad key \"a\" for: %{:b => 2, :c => 3, \"a\" => 1}"

iex> {:error, error} = 42 |> opzioni_merge
...> error |> Exception.message
"opzioni invalid, got: 42"
Link to this function opzioni_normalise(opzioni \\ []) View Source
opzioni_normalise(any()) :: {:ok, opts()} | {:error, error()}

opzioni_normalise/1 takes a value tries to normalise it into an opzioni, returning {:ok, opzioni}.

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

Examples

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

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

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

iex> [ [a: 1, b: 2, c: 3], %{x: 10, y: 11, z: 12}] |> opzioni_normalise
{:ok, [[a: 1, b: 2, c: 3], [x: 10, y: 11, z: 12]]}

iex> {:error, error} = %{"a" => 1, :b => 2, :c => 3} |> opzioni_normalise
...> error |> Exception.message
"bad key \"a\" for: %{:b => 2, :c => 3, \"a\" => 1}"

iex> {:error, error} = 42 |> opzioni_normalise
...> error |> Exception.message
"opzioni invalid, got: 42"

iex> [a: nil, b: [:b1], c: [:c1, :c2, :c3]] |> opzioni_normalise
{:ok, [[a: nil, b: [:b1], c: [:c1, :c2, :c3]]]}
Link to this function opzioni_validate(opzioni \\ []) View Source
opzioni_validate(any()) :: {:ok, opts()} | {:error, error()}

opzioni_validate/1 takes a value and validates it is an opzioni, returning {:ok, opzioni}.

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

Examples

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

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

iex> {:error, error} = [a: 1, b: 2, c: 3] |> opzioni_validate
...> error |> Exception.message
"opts invalid, got: {:a, 1}"

iex> {:error, error} = %{a: 1, b: 2, c: 3} |> opzioni_validate
...> error |> Exception.message
"opzioni invalid, got: %{a: 1, b: 2, c: 3}"

iex> {:error, error} = [[a: 1, b: 2, c: 3], %{x: 10, y: 11, z: 12}] |> opzioni_validate
...> error |> Exception.message
"opts invalid, got: %{x: 10, y: 11, z: 12}"

iex> {:error, error} = 42 |> opzioni_validate
...> error |> Exception.message
"opzioni invalid, got: 42"