Agenda.Predicate (Agenda v0.1.0)

Copy Markdown View Source

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.

t()

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

op()

@type op() :: :at_least | :at_most | :exactly | :any_of | :all_of | :none_of

The supported comparisons.

t()

@type t() :: t(op())

A comparison a resource attribute must satisfy.

t(op)

@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

all_of(values)

@spec all_of([term()]) :: t()

The attribute — itself a list — must contain every one of values.

Arguments

  • values is a list of required members.

Returns

Examples

iex> Agenda.Predicate.all_of([:projector, :whiteboard]).op
:all_of

any_of(values)

@spec any_of([term()]) :: t()

The attribute must be one of values.

Arguments

  • values is a list of acceptable values.

Returns

Examples

iex> Agenda.Predicate.any_of([:sydney, :melbourne]).op
:any_of

at_least(value)

@spec at_least(term()) :: t(:at_least)

The attribute must be greater than or equal to value.

Arguments

  • value is the inclusive lower bound.

Returns

Examples

iex> Agenda.Predicate.at_least(8).operand
8

at_most(value)

@spec at_most(term()) :: t(:at_most)

The attribute must be less than or equal to value.

Arguments

  • value is the inclusive upper bound.

Returns

Examples

iex> Agenda.Predicate.at_most(4).operand
4

coerce(predicate)

@spec coerce(t() | term()) :: t()

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

  • value is a t/0 or any bare term.

Returns

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

describe(predicate)

@spec describe(t()) :: String.t()

A phrase describing what predicate demands, for use in an explanation.

Arguments

  • predicate is a t/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"}

exactly(value)

@spec exactly(term()) :: t(:exactly)

The attribute must equal value. A bare value in a requirement is sugar for this.

Arguments

  • value is the required value.

Returns

Examples

iex> Agenda.Predicate.exactly(:sydney).operand
:sydney

none_of(values)

@spec none_of([term()]) :: t()

The attribute must be none of values.

Arguments

  • values is a list of disqualifying values.

Returns

Examples

iex> Agenda.Predicate.none_of([:basement]).op
:none_of

satisfied?(predicate, value)

@spec satisfied?(t(), term()) :: boolean()

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

  • predicate is a t/0.

  • value is the resource's attribute value, or nil when absent.

Returns

  • true or false.

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