plymio_vekil v0.1.0 Plymio.Vekil.Forom.Proxy View Source
The module implements the Plymio.Vekil.Forom protocol and manages
a proxy.
A proxy forom holds a reference to another proxy in its :forom
field.
When a proxy forom is produced or realised the proxy in the
:forom fields is used, together with the vekil, in a call to
Plymio.Vekil.proxy_fetch/2 and the forom returned by the fetch
is produced or realised.
If the proxy form does not have a vekil an error result is returned.
In many examples the proxy is an atom but that is not a constraint: its type (e.g. atom, string, whatever) is defined and decided by the vekil. (So, for example, looking up an atom in a vekil where the proxies (“keys”) are strings will never succeed). The vekils used in the doctests below use atom proxies.
See Plymio.Vekil.Forom for the definitions of the protocol functions.
See Plymio.Vekil for an explanation of the test environment.
Module State
See Plymio.Vekil.Forom for the common fields.
The default :produce_default is an empty list.
The default :realise_default is the unset value (Plymio.Fontais.the_unset_value/0).
The module’s state is held in a struct with the following field(s):
| Field | Aliases | Purpose |
|---|---|---|
:forom | holds the proxy |
Link to this section Summary
Functions
new/1 takes an optional opts and creates a new forom returning {:ok, forom}
normalise/1 creates a new forom from its argument unless the argument is already one
produce/2 takes a forom and an optional opts
realise/2 takes a forom and an optional opts, calls
produce/2, and then gets (Keyword.get_values/2) the :forom key values
Link to this section Types
Link to this section Functions
new/1 takes an optional opts and creates a new forom returning {:ok, forom}.
Examples
iex> {:ok, forom} = new()
...> match?(%FOROMPROXY{}, forom)
true
Plymio.Vekil.Utility.forom?/1 returns true if the value implements Plymio.Vekil.Forom
iex> {:ok, forom} = new()
...> forom |> Plymio.Vekil.Utility.forom?
true
The proxy is passed using the :forom key:
iex> {:ok, forom1} = FOROMFORM.new(forom: :x_add_1)
...> {:ok, forom} = new(forom: forom1)
...> forom |> Plymio.Vekil.Utility.forom?
true
normalise/1 creates a new forom from its argument unless the argument is already one.
For a proxy forom normalise/1 offers a small way to reduce boilerplate.
Examples
Here the argument is an atom and a proxy forom is created. Note a vekil is needed to resolve the proxy.
iex> {:ok, %FOROMPROXY{} = forom} = :x_mul_x |> normalise
...> realise_opts = [vekil: vekil_helper_form_vekil_example1()]
...> {:ok, {form, _}} = forom |> FOROMPROT.realise(realise_opts)
...> form |> harnais_helper_test_forms!(binding: [x: 3])
{9, ["x = x * x"]}
The function accepts any value as the proxy; it is only when the
proxy is accessed by a vekil (e.g. Plymio.Vekil.proxy_fetch/2)
can the type of the proxy be known (e.g. an atom) and invalid ones caught.
iex> {:ok, %FOROMPROXY{} = forom} = "maybe a proxy" |> normalise
...> realise_opts = [vekil: vekil_helper_form_vekil_example1()]
...> {:error, error} = forom |> FOROMPROT.realise(realise_opts)
...> error |> Exception.message
"proxy invalid, got: maybe a proxy"
produce/2 takes a forom and an optional opts.
The value in the :forom field is used, together with the essential vekil, in a call to
Plymio.Vekil.proxy_fetch/2 and the forom returned by the fetch.
is produced.
Examples
iex> {:ok, forom} = new(forom: :x_add_1)
...> produce_opts = [vekil: vekil_helper_form_vekil_example1()]
...> {:ok, {product, _}} = forom |> FOROMPROT.produce(produce_opts)
...> product |> Keyword.get_values(:forom)
...> |> harnais_helper_test_forms!(binding: [x: 7])
{8, ["x = x + 1"]}
A variation of the above example showing that the product has
multiple :forom keys, one for each of the constituent, terminal
forom in the x_funs list forom.
iex> {:ok, forom} = new(forom: :x_funs)
...> produce_opts = [vekil: vekil_helper_form_vekil_example1()]
...> {:ok, {product, _}} = forom |> FOROMPROT.produce(produce_opts)
...> [:forom] = product |> Keyword.keys |> Enum.uniq
...> 3 = product |> Keyword.keys |> length
...> product |> Keyword.get_values(:forom)
...> |> harnais_helper_test_forms!(binding: [x: 7])
{63, ["x = x + 1", "x = x * x", "x = x - 1"]}
A proxy forom can reference another proxy which is itself a proxy forom proxy forom and so on:
iex> {:ok, %VEKILFORM{} = vekil} = [dict: [
...> p1: :p2,
...> p2: :p3,
...> p3: "The End"
...> ]] |> VEKILFORM.new()
...> {:ok, forom} = new(forom: :p1)
...> produce_opts = [vekil: vekil]
...> {:ok, {product, _}} = forom |> FOROMPROT.produce(produce_opts)
...> product |> Keyword.get_values(:forom)
["The End"]
There must be a valid vekil:
iex> {:ok, forom} = new(forom: :x_add_1)
...> produce_opts = [vekil: :invalid_vekil]
...> {:error, error}= forom |> FOROMPROT.produce(produce_opts)
...> error |> Exception.message
"vekil invalid, got: :invalid_vekil"
iex> {:ok, forom} = new(forom: :not_a_proxy)
...> {:error, error}= forom |> FOROMPROT.produce
...> error |> Exception.message
"vekil is unset"
An empty forom does not produce any :forom keys:
iex> {:ok, forom} = new()
...> {:ok, {product, _}} = forom |> FOROMPROT.produce
...> product |> Keyword.get_values(:forom)
[]
realise/2 takes a forom and an optional opts, calls
produce/2, and then gets (Keyword.get_values/2) the :forom key values.
The example are reqorked ones from produce/2
Examples
iex> {:ok, forom} = new(forom: :x_funs)
...> realise_opts = [vekil: vekil_helper_form_vekil_example1()]
...> {:ok, {forms, _}} = forom |> FOROMPROT.realise(realise_opts)
...> 3 = forms |> length
...> forms |> harnais_helper_test_forms!(binding: [x: 7])
{63, ["x = x + 1", "x = x * x", "x = x - 1"]}
iex> {:ok, %VEKILFORM{} = vekil} = [dict: [
...> p1: :p2,
...> p2: :p3,
...> p3: "The End"
...> ]] |> VEKILFORM.new()
...> {:ok, forom} = new(forom: :p1)
...> realise_opts = [vekil: vekil]
...> {:ok, {values, _}} = forom |> FOROMPROT.realise(realise_opts)
...> values
["The End"]
update/2 implements Plymio.Vekil.Forom.update/2.
Examples
iex> {:ok, forom} = new(forom: :x_add_1)
...> {:ok, forom} = forom |> FOROMPROT.update(forom: :x_mul_x)
...> realise_opts = [vekil: vekil_helper_form_vekil_example1()]
...> {:ok, {form, _}} = forom |> FOROMPROT.realise(realise_opts)
...> form |> harnais_helper_test_forms!(binding: [x: 3])
{9, ["x = x * x"]}