ebenbild
A tiny library to get predicates from example data for Clojure(Script)
Can be used to match maps by examples. To find all persons whose name includes "Bob" you could write
(def persons [{:name "Bob" :age 31} {:name "Al" :age 32} {:name "Cory" :age 44}])
(filter (like {:name "Bob"}) persons)
=> ({:name "Bob" :age 31})
Usage
Simply add the following entry to your :dependencies
:
[ebenbild "0.2.0"]
Ebenbild consists of two core functions: like
and like?
.
-
(like arg)
returns a predicate that matches look-a-likes of the given arg. -
(like? arg compare-to)
generates a predicate using(like arg)
and calls it oncompare-to
. When using a predicate more than one time you should uselike
instead oflike?
.
So what are look-a-likes?
Depending on the given arg, like
will generate predicates that match as follows:
-
Fn
assumes that it's already a predicate and just returns it.(like? even? 4) => true
(like? even? 5) => false
-
String
matches all strings that includes the given string.(like? "AB" "elvABuunre") => true
(like? "AB" "CANRIBAean") => false
-
Pattern
matches if the pattern matches.(like? #"[a-z]" "a") => true
(like? #"[a-z]" "az") => false
-
Keyword
matches the same keyword, if given no namespace matches all keywords with the same name(like? :a :a) => true
(like? :a/a :a) => false
(like? :a :a/a) => true
(like? :a/a :a/a) => true
-
Map
calls like on all vals (recursively) and matches another map if all keys are contained and their vals match.(like? {:a "A"} {:a "BAB" :b 123}) => true
(like? {:a {:b "A"}} {:a {:b "LAL" :c 1}}) => true
(like? {:a 1} {:a "A"}) => false
-
IPersistentVector
calls like on all entries (recursively) and matches any sequential with the same number of elements where all entries match the corresponding predicate.(like? [1 2 3] '(1 2 3)) => true
(like? ["1" {:a 1} ["A"]] ["A1A" {:a 1 :b 2 :c 3} ["XA"]]) => true
(like? [1 2] [1 2 3]) => false
-
ANY
(a symbol in the core namespace), will always return true.(like? ANY 1) => true
(like? ANY "Foo") => true
- everything else will fall back to a equality check using
=
.
You can extend like
by extending the EbenbildPred
Protocol.
Other functions
Ebenbild provides some functions often used with like.
-
(unlike x)
the complement of(like x)
-
(like-one x y z ...)
returns a predicate that matches if any given data is a look-a-like -
(like-all x y z ...)
returns a predicate that matches if all given data is a look-a-like
Properties of ebenbild predicates
The following properties should hold for every predicate created with like
.
Please create an issue if you find some edge case that doesn't.
-
Identity:
(like? x x)
/((like x) x)
is always true.- with the exception of functions and regexes
-
Just Predicates: The predicate always returns
true
orfalse
- Failsafe: The predicate throws no errors.
Further notices
Because like/unlike/like-one/like-all
returns predicates and (like predicate)
returns the predicate itself, you can nest different like
. For example
(like {:Type (like-one :simple :complex))
returns a predicate that matches every map that has a :Type
key with either :simple
or :complex
as the value.
Because like-one/like-all
are functions (unlike clojure.core or/and
) you can
apply them on seqs of data to get a predictate that matches look-a-likes for one or all of them.
License
Copyright © 2018 Albrecht Schmidt
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.