((finder '{?k ?v} identity) {:a 1 :b 2})
;; =>
{?k :a, ?v 1}
((searcher '{?k ?v} identity) {:a 1 :b 2})
;; =>
({?k :a, ?v 1} {?k :b, ?v 2})
There are details about the implementation in the comments but the gist here is that there is a framework for building up pattern matchers functionally. For now, this framework is largely private and only REPL tested and approved.
The reason it is private is because 1. there are no unit tests, 2. there is no interpretation for substitution, and 3. pending the substitution interpretation I may want to move things around.
What is nice, however, is that this model is pretty flexible and once the second items is taken care of and things can be made public, more interesting runtimes can be developed.
$ bb --classpath src
Babashka v0.2.3 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.
user=> (require '[meander.interpreter.epsilon :as m])
nil
user=> (m/searcher '{?k ?v} identity)
#object[sci.impl.fns$eval_fn$fn__12966 0x5212d6ab "sci.impl.fns$eval_fn$fn__12966@11052c160"]
user=> (*1 {:a 1 :b 2 :c 3})
({?k :c, ?v 3} {?k :b, ?v 2} {?k :a, ?v 1})
user=> (m/finder '{?k ?v} identity)
#object[sci.impl.fns$eval_fn$fn__12966 0x62700f6 "sci.impl.fns$eval_fn$fn__12966@1109c9048"]
user=> (*1 {:a 1 :b 2 :c 3})
{?k :c, ?v 3}
The runtime bit is nice. Both searcher
and finder
use the same factory functions to build up an über factory which takes a runtime and produces a implementation specific matching function.
In the case of searcher
it produces a sequence of results; with finder
it reduces the space down to the first one it finds. The details are in the runtime.
Before I merge, cut, and release, I need to add some unit tests for the interpreter namespace.