The attribute predicate vocabulary — the words a requirement is written in.
These deliberately mirror the duration predicates Tempo already
provides (Tempo.at_least?/2, Tempo.at_most?/2,
Tempo.exactly?/2). One vocabulary applies to durations on the
temporal side and to attributes here, so there is one set of words to
learn rather than two.
A predicate knows how to describe itself, which is what lets a failed
match explain why in a sentence rather than returning false.
Examples
iex> import Agenda.Predicate
iex> satisfied?(at_least(8), 12)
true
iex> import Agenda.Predicate
iex> describe(at_least(8))
"at least 8"
Summary
Types
The supported comparisons.
A comparison a resource attribute must satisfy.
A comparison whose operator is known — t(:at_least) is what
at_least/1 returns. The constructors are specified this precisely so
that a misplaced predicate is a type error rather than a runtime
surprise.
Functions
The attribute — itself a list — must contain every one of values.
The attribute must be one of values.
The attribute must be greater than or equal to value.
The attribute must be less than or equal to value.
Coerce a bare value into a predicate, leaving predicates untouched.
A phrase describing what predicate demands, for use in an
explanation.
The attribute must equal value. A bare value in a requirement is
sugar for this.
The attribute must be none of values.
true when value satisfies predicate.
Types
@type op() :: :at_least | :at_most | :exactly | :any_of | :all_of | :none_of
The supported comparisons.
A comparison a resource attribute must satisfy.
@type t(op) :: %Agenda.Predicate{op: op, operand: term()}
A comparison whose operator is known — t(:at_least) is what
at_least/1 returns. The constructors are specified this precisely so
that a misplaced predicate is a type error rather than a runtime
surprise.
Functions
The attribute — itself a list — must contain every one of values.
Arguments
valuesis a list of required members.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.all_of([:projector, :whiteboard]).op
:all_of
The attribute must be one of values.
Arguments
valuesis a list of acceptable values.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.any_of([:sydney, :melbourne]).op
:any_of
The attribute must be greater than or equal to value.
Arguments
valueis the inclusive lower bound.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.at_least(8).operand
8
The attribute must be less than or equal to value.
Arguments
valueis the inclusive upper bound.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.at_most(4).operand
4
Coerce a bare value into a predicate, leaving predicates untouched.
This is what lets video_conferencing: true and
seats: at_least(8) sit side by side in the same requirement.
Arguments
valueis at/0or any bare term.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.coerce(true)
%Agenda.Predicate{op: :exactly, operand: true}
iex> predicate = Agenda.Predicate.at_least(8)
iex> Agenda.Predicate.coerce(predicate) == predicate
true
A phrase describing what predicate demands, for use in an
explanation.
Arguments
predicateis at/0.
Returns
- a phrase such as
"at least 8", readable inside a sentence.
Examples
iex> import Agenda.Predicate
iex> {describe(at_least(8)), describe(exactly(true))}
{"at least 8", "true"}
The attribute must equal value. A bare value in a requirement is
sugar for this.
Arguments
valueis the required value.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.exactly(:sydney).operand
:sydney
The attribute must be none of values.
Arguments
valuesis a list of disqualifying values.
Returns
- a
t/0.
Examples
iex> Agenda.Predicate.none_of([:basement]).op
:none_of
true when value satisfies predicate.
A nil value — the attribute is absent from the resource — never
satisfies a predicate, except none_of/1, which an absent attribute
trivially satisfies.
Arguments
predicateis at/0.valueis the resource's attribute value, ornilwhen absent.
Returns
trueorfalse.
Examples
iex> import Agenda.Predicate
iex> {satisfied?(at_least(8), 8), satisfied?(at_least(8), 4)}
{true, false}
iex> import Agenda.Predicate
iex> satisfied?(at_least(8), nil)
false