matcher (matcher v1.1.0)

View Source

A simple expression matcher and evaluator for Erlang.

Evaluates expressions given as tuples of the form:
  • {Op, Arg} - Unary operators (e.g. not)
  • {Op, Arg1, Arg2} - Binary operators (e.g. eq, lt)
  • {Op, [Arg, ...]} - N-ary operators (e.g. and, or)

Quick Start

   true = matcher:eval({'=', <<"Albert">>, <<"Albert">>}).
   true = matcher:eval({'=~', <<"Albert">>, <<"albert">>}).
   true = matcher:eval({'?', <<"bert">>, <<"Albert">>}).

Using a Provider

A provider resolves values that cannot be evaluated further:

   Map = #{name => <<"Albert">>, age => 42}.
   true = matcher:eval(Map, {'=', name, <<"Albert">>}).
   true = matcher:eval(Map, {'>', age, 18}).

eval vs match

eval/1,2 returns the evaluated value as-is. match/1,2 enforces a boolean result and returns {error, {unevaluated_expression, Expr}} for non-boolean results.

Summary

Functions

Evaluates the expression using the identity provider.

Evaluates the expression using the given provider or map.

Returns a provider that returns its argument unchanged.

Returns a provider that looks up values in the given map. If the key is not found, the key itself is returned.

Evaluates the expression and returns a strict boolean.

Evaluates the expression with a provider and returns a strict boolean.

Types

binary_op/0

-type binary_op() ::
          eq | '=' | '==' | '=~' | lt | '<' | '<~' | gt | '>' | '>~' | le | '<=' | '=<' | '<=~' |
          '=<~' | ge | '>=' | '=>' | '>=~' | '=>~' | part_of | '?' | '?~' |
          {eq, case_insensitive} |
          {lt, case_insensitive} |
          {gt, case_insensitive} |
          {le, case_insensitive} |
          {ge, case_insensitive} |
          {part_of, case_insensitive}.

expression/0

-type expression() ::
          {unary_op(), expression()} |
          {binary_op(), term(), term()} |
          {nary_op(), [expression()]} |
          term().

nary_op/0

-type nary_op() :: 'and' | '&' | 'or' | '|'.

provider/0

-type provider() :: fun((term()) -> term()).

unary_op/0

-type unary_op() :: 'not' | '!'.

Functions

eval(Expression)

-spec eval(expression()) -> term().

Evaluates the expression using the identity provider.

  true = matcher:eval({'=', <<"A">>, <<"A">>}).
  false = matcher:eval({'<', 5, 3}).
  true = matcher:eval({'?', <<"ber">>, <<"Albert">>}).

eval(Provider, Expression)

-spec eval(provider() | map(), expression()) -> term().

Evaluates the expression using the given provider or map.

When a map is given, it is automatically wrapped with map_provider/1.

  Map = #{sender => <<"WDR">>}.
  true = matcher:eval(Map, {'=', sender, <<"WDR">>}).
  true = matcher:eval(Map, {'=~', sender, <<"wdr">>}).

identity_provider()

-spec identity_provider() -> provider().

Returns a provider that returns its argument unchanged.

This is the default provider used by eval/1 and match/1.

  P = matcher:identity_provider().
  <<"hello">> = P(<<"hello">>).

map_provider(Map)

-spec map_provider(map()) -> provider().

Returns a provider that looks up values in the given map. If the key is not found, the key itself is returned.

  P = matcher:map_provider(#{name => <<"Alice">>}).
  <<"Alice">> = P(name).
  <<"literal">> = P(<<"literal">>).

match(Expression)

-spec match(expression()) -> true | false | {error, {unevaluated_expression, term()}}.

Evaluates the expression and returns a strict boolean.

Returns true, false, or {error, {unevaluated_expression, Expr}} if the expression cannot be fully evaluated to a boolean.

  true = matcher:match({'=', <<"A">>, <<"A">>}).
  {error, _} = matcher:match({'*', <<"A">>, <<"B">>}).

match(Provider, Expression)

-spec match(provider() | map(), expression()) ->
               true | false | {error, {unevaluated_expression, term()}}.

Evaluates the expression with a provider and returns a strict boolean.

Returns true, false, or {error, {unevaluated_expression, Expr}} if the expression cannot be fully evaluated to a boolean.

  Map = #{name => <<"Alice">>}.
  true = matcher:match(Map, {'=', name, <<"Alice">>}).
  false = matcher:match(Map, {'=', name, <<"Bob">>}).