Just rewrote my matcher app in Erlang for evaluating expressions against maps with a funny query language build out of Erlang tuples.
Evaluates expressions like
matcher:eval({'=', <<"Albert">>, <<"Albert">>})
Expressions are tuples in one of the following form:
{ Op, Arg }
{ Op, Arg1, Arg2 }
{ Op, [Arg, ...] }
Expressions can be nested: Any argument can be an expression again:
{'&', [{'=', <<"Albert">>, <<"Albert">>}, {'=', <<"Berta">>, <<"Albert">>}]}
matcher:eval/2 allows to specify a Provider, which is a fun/1 evaluates expression that can not be evaluated any further.
Example: If you have a map with atoms as keys, these keys can be replaces by its corresponding value.
Map = #{ name => <<"Albert">> }.
true = matcher:eval(Map, {'=', name, <<"Albert">>}).
matcher:eval(Map, Expr) is short for matcher:eval(map_provider(Map), Expr).
You can use any fun/1 as a provider.
BTW: If you like you can specify new operators with such a function, just handle something like {my_cool_op, A, B} in your function.
List of Operators:
- One operand
!,not
- Many operands (list)
&,and|,or
- Two operands
<,lt: less then<~,{lt, case_insensitive}: less then (case insensitive)>,gt: greater then>~,{gt, case_insensitive}: greater then (case insensitive)>=,=>,le: less then or equal>=~,=>~,{lt, case_insensitive}: less then or equal (case insensitive)<=,=<,le: less then or equal<=~,=<~,{lt, case_insensitive}: less then or equal (case insensitive)=,==,eq: equal=~,{eq, case_insensitive}: equal (case insensitive)?,part_of: first string is part of second?~,{part_of, case_insensitive}: first string is part of second (case insensitive)
See ./test/matcher_SUITE.erl
License
License is MIT … but I like to hear from you, if you think this app is useful. :-)