The run of a decision table (DMN 1.6, clause 8 and 10.3.2.10), for both backends.
A backend gives the table its parts as functions, and this module does what the specification says of them:
- The input expressions have been evaluated, in order, and
inputsare their values, each with the function that tests it against theinputValuesof its column, if it has some. - A rule matches when every input satisfies the input entry of its column. An entry is a function of the input value
and the environment that gives
trueorfalse(the unary tests of an entry are satisfied or not, nevernull, andnot(…)is satisfied by an input that none of its tests matches). No entry is-, and satisfied by any input; if the column has input values it is satisfied by an input that satisfies them. A rule stops at the first entry that is not satisfied. - The hit policy chooses among the rules that match, and the outputs of those are computed, and only those: an output entry of a rule that does not count is not run.
- No rule counts: the default output, or
null.
| Policy | Result |
|---|---|
:unique | the output of the one rule; more than one is null with the error :unique_hit_policy_violated |
:first | the output of the first rule |
:any | the output of the first rule, if the outputs of all of them are equal (=), else null with :any_hit_policy_violated |
:priority | the output that comes first in the output values; one that is not among them is null with :output_not_in_values |
:output_order | the outputs in the order of the output values |
:rule_order | the list of the outputs, in the order of the rules |
:collect | the list of the outputs, or sum, count, min or max of it with an aggregation |
The output of a rule is its output entry, or, for a table of several outputs, a context of them by the names of the outputs. The order of the priority policies is by the output values of the first output, then of the second, and so on; an output that has none is not part of it.
Every error here is null for the table, reported at the span of the node, as the errors of the operators are (and ends a
mode: :strict run).
Summary
Types
A function of an input and the environment that tells whether the input satisfies the entry of a rule.
An input: its value, and the test against the input values of its column, if it has one.
An output: the output values (the order of the priority policies) and the default output entry, if it has them.
A rule: its id, one entry for each input (nil is -), and one output entry for each output.
A function of the environment that computes a part of the table.
Functions
Runs a table.
Types
@type entry() :: (Feel.Value.t(), Feel.Runtime.Env.t() -> {boolean(), Feel.Runtime.Env.t()})
A function of an input and the environment that tells whether the input satisfies the entry of a rule.
@type input() :: {Feel.Value.t(), entry() | nil}
An input: its value, and the test against the input values of its column, if it has one.
@type options() :: %{ policy: :unique | :first | :any | :priority | :output_order | :rule_order | :collect, aggregation: :sum | :count | :min | :max | nil, names: [String.t() | nil], span: Feel.Diagnostic.span() }
An output: the output values (the order of the priority policies) and the default output entry, if it has them.
A rule: its id, one entry for each input (nil is -), and one output entry for each output.
@type thunk() :: (Feel.Runtime.Env.t() -> {Feel.Value.t(), Feel.Runtime.Env.t()})
A function of the environment that computes a part of the table.
Functions
@spec run(Feel.Runtime.Env.t(), options(), [input()], [rule()], [output()]) :: {Feel.Value.t(), Feel.Runtime.Env.t()}
Runs a table.
iex> env = Feel.Runtime.Env.new()
iex> equals = fn expected -> fn input, env -> {input == expected, env} end end
iex> rules = [{"r1", [equals.("a")], [fn env -> {1, env} end]}, {"r2", [equals.("b")], [fn env -> {2, env} end]}]
iex> options = %{policy: :unique, aggregation: nil, names: [nil], span: {0, 1}}
iex> {value, _env} = Feel.Runtime.DecisionTable.run(env, options, [{"b", nil}], rules, [{nil, nil}])
iex> value
2