plymio_vekil v0.1.0 Plymio.Vekil.Term View Source
This module implements the Plymio.Vekil protocol using a Map where the
proxies (keys) are atoms and the foroms (values) hold any valid term.
The default when creating a term vekil is to create a
Plymio.Vekil.Forom.Term forom but any vekil can hold any
forom.
See Plymio.Vekil for the definitions of the protocol functions.
Module State
The module’s state is held in a struct with the following field(s):
| Field | Aliases | Purpose |
|---|---|---|
:dict | :d | hold the map of proxies v forom |
:forom_normalise | see Plymio.Vekil.Form field description | |
:proxy_normalise | see Plymio.Vekil.Form field description |
See Plymio.Vekil.Form for an explanation of :forom_normalise and :proxy_normalise.
Test Environent
See also notes in Plymio.Vekil.
The vekil created in the example below of new/1 is returned by
vekil_helper_term_vekil_example1/0.
iex> {:ok, vekil} = new()
...> dict = [
...> x_add_1: quote(do: x = x + 1),
...> x_mult_x: quote(do: x = x * x),
...> x_sub_1: quote(do: x = x - 1),
...> value_42: 42,
...> value_x_add_1: :x_add_1,
...> proxy_x_add_1: [forom: :x_add_1] |> Plymio.Vekil.Forom.Proxy.new!
...> ]
...> {:ok, vekil} = vekil |> update(dict: dict)
...> match?(%VEKILTERM{}, vekil)
true
Link to this section Summary
Link to this section Types
Link to this section Functions
See Plymio.Vekil.forom_normalise/2
The default action is to create a term forom (Plymio.Vekil.Forom.Term).
Examples
Here the value being normalised is a keyword:
iex> %VEKILTERM{} = vekil = vekil_helper_term_vekil_example1()
...> value = [a: 1, b: 2, c: 3]
...> {:ok, {forom, %VEKILTERM{}}} = vekil |> VEKILPROT.forom_normalise(value)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
[a: 1, b: 2, c: 3]
An atom is normalise to a term forom, not a proxy forom:
iex> %VEKILTERM{} = vekil = vekil_helper_term_vekil_example1()
...> value = :x_add_1
...> {:ok, {forom, %VEKILTERM{}}} = vekil |> VEKILPROT.forom_normalise(value)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
:x_add_1
An existing forom is returned unchanged.
iex> %VEKILTERM{} = vekil = vekil_helper_term_vekil_example1()
...> {:ok, %Plymio.Vekil.Forom.Form{} = forom} = quote(do: x = x + 1)
...> |> Plymio.Vekil.Forom.Form.normalise
...> {:ok, {forom, %VEKILTERM{}}} = vekil |> VEKILPROT.forom_normalise(forom)
...> {:ok, {forms, _}} = forom |> FOROMPROT.realise
...> forms |> harnais_helper_test_forms!(binding: [x: 2])
{3, ["x = x + 1"]}
Note: the proxy is not normalised in any way.
Examples
Here a known proxy is tested for:
iex> vekil_helper_term_vekil_example1()
...> |> VEKILPROT.has_proxy?(:x_sub_1)
true
An unknown proxy returns false
iex> vekil_helper_term_vekil_example1()
...> |> VEKILPROT.has_proxy?(:not_a_proxy)
false
iex> vekil_helper_term_vekil_example1()
...> |> VEKILPROT.has_proxy?(%{a: 1})
false
new/1 takes an optional opts and creates a new vekil returning {:ok, vekil}.
Examples
iex> {:ok, vekil} = new()
...> match?(%VEKILTERM{}, vekil)
true
Plymio.Vekil.Utility.vekil?/1 returns true if the value implements Plymio.Vekil
iex> {:ok, vekil} = new()
...> vekil |> Plymio.Vekil.Utility.vekil?
true
The vekil dictionary can be supplied as a Map or Keyword. It
will be validated to ensure all the proxies are atoms and all the
forom are valid forms.
A term vekil does not recognise / normalise atom values
(e.g. the :x_add_1 value for :value_x_add_1 below) as a
proxy; it is just a term. When a proxy is wanted, it must be
given explicitly (see entry for proxy_x_add_1). See also the fetch examples.
iex> {:ok, vekil} = [dict: [
...> x_add_1: [forom: quote(do: x = x + 1)] |> FOROMFORM.new!,
...> x_mul_x: [forom: quote(do: x = x * x)] |> FOROMFORM.new!,
...> x_sub_1: [forom: quote(do: x = x - 1)] |> FOROMFORM.new!,
...> value_42: 42,
...> value_x_add_1: :x_add_1,
...> proxy_x_add_1: [forom: :x_add_1] |> Plymio.Vekil.Forom.Proxy.new!
...> ]] |> new()
...> match?(%VEKILTERM{}, vekil)
true
See Plymio.Vekil.proxy_delete/2
Note proxies are normalised.
Examples
Here a known proxy is deleted and then fetched, causing an error:
iex> {:ok, %VEKILTERM{} = vekil} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_delete(:x_sub_1)
...> {:error, error} = vekil |> VEKILPROT.proxy_fetch([:x_add_1, :x_sub_1])
...> error |> Exception.message
"proxy invalid, got: :x_sub_1"
This example deletes :x_mul_x and but provides quote(do: x = x *
x * x) as the default in the following get:
iex> {:ok, %VEKILTERM{} = vekil} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_delete(:x_mul_x)
...> {:ok, {forom, %VEKILTERM{}}} = vekil
...> |> VEKILPROT.proxy_get([:x_add_1, :x_mul_x, :x_sub_1], quote(do: x = x * x * x))
...> {:ok, {forms, _}} = forom |> FOROMPROT.realise
...> forms |> harnais_helper_test_forms!(binding: [x: 7])
{511, ["x = x + 1", "x = x * x * x", "x = x - 1"]}
Deleting unknown proxies does not cause an error:
iex> {:ok, %VEKILTERM{} = vekil} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_delete([:x_sub_1, :not_a_proxy, :x_mul_x])
...> vekil |> Plymio.Vekil.Utility.vekil?
true
See Plymio.Vekil.proxy_fetch/2.
Examples
A single proxy is requested:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch(:value_42)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
42
Two proxies are requested:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch([:value_42, :value_x_add_1])
...> {:ok, {values, _}} = forom |> FOROMPROT.realise
...> values
[42, :x_add_1]
In the example vekil the proxy :value_x_add_ is a term
forom holding a simple atom (:x_add_):
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch(:value_x_add_1)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
:x_add_1
But the proxy :proxy_x_add_1 does hold a proxy forom pointing to the :x_add_1 proxy:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_get(:proxy_x_add_1)
...> {:ok, {form, _}} = forom |> FOROMPROT.realise
...> form |> harnais_helper_test_forms!(binding: [x: 7])
{8, ["x = x + 1"]}
proxies is nil / empty. Note the use and override of the :realise_default field:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch(nil)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value |> Plymio.Fontais.Guard.is_value_unset
true
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch([])
...> {:ok, {value, _}} = forom |> FOROMPROT.realise(realise_default: nil)
...> value
nil
One or more proxies not found
iex> {:error, error} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch(:not_a_proxy)
...> error |> Exception.message
"proxy invalid, got: :not_a_proxy"
iex> {:error, error} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_fetch([:missing_proxy, :x_sub_1, :not_a_proxy])
...> error |> Exception.message
"proxies invalid, got: [:missing_proxy, :not_a_proxy]"
Examples
A single known, proxy is requested with no default
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_get(:value_42)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
42
Two known proxies are requested:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_get([:value_42, :value_x_add_1])
...> {:ok, {values, _}} = forom |> FOROMPROT.realise
...> values
[42, :x_add_1]
A single unknown, proxy is requested with no default. The the
:realise_default has been overridden.
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_get(:not_a_proxy)
...> {:ok, {value, _}} = forom
...> |> FOROMPROT.realise(realise_default: :proxy_not_found)
...> value
:proxy_not_found
Examples
A single unknown proxy is requested with a default:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_get(:value_42, 123)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
42
A mix of known and unknown proxies, together with a default:
iex> {:ok, {forom, %VEKILTERM{}}} = vekil_helper_term_vekil_example1()
...> |> VEKILPROT.proxy_get([:missing_proxy, :value_42, :not_a_proxy], 123)
...> {:ok, {values, _}} = forom |> FOROMPROT.realise
...> values
[123, 42, 123]
Examples
A list of {proxy,value} tuples can be given. Since a form vekil’s proxy is
an atom, Keyword syntax can be used:
iex> {:ok, %VEKILTERM{} = vekil} = VEKILTERM.new()
...> {:ok, %VEKILTERM{} = vekil} = vekil |> VEKILPROT.proxy_put(
...> one: 1, due: :two, tre: "three")
...> {:ok, {forom, %VEKILTERM{}}} = vekil |> VEKILPROT.proxy_fetch(:tre)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
"three"
Examples
This example puts a proxy into an empty vekil and then fetches it.
iex> {:ok, %VEKILTERM{} = vekil} = VEKILTERM.new()
...> {:ok, %VEKILTERM{} = vekil} = vekil
...> |> VEKILPROT.proxy_put(:z, %{a: 1})
...> {:ok, {forom, %VEKILTERM{}}} = vekil |> VEKILPROT.proxy_fetch(:z)
...> {:ok, {value, _}} = forom |> FOROMPROT.realise
...> value
%{a: 1}
update/2 takes a vekil and opts and update the field(s) in the
vekil from the {field,value} tuples in the opts.
Examples
iex> {:ok, vekil} = new()
...> dict = [
...> an_integer: 42,
...> an_atom: :nothing_special,
...> a_string: "Hello World!",
...> ]
...> {:ok, vekil} = vekil |> update(dict: dict)
...> match?(%VEKILTERM{}, vekil)
true