I needed a simple template system. I think this fits the bill for both simple and easy:
(m/rewrite {:keys #{::name ::state}
:template ["here is some data for" ::name
{:name ::name
:state ::state}]
:values {::name "Mark"
::state "California"}}
{:keys ?keys
:values ?values
:template (m/$ ?ctx (m/pred (partial contains? ?keys) ?key))}
(m/cata {:keys ?keys, :values ?values
:template (m/app ?ctx (m/app ?values ?key))})
{:template ?result} ?result)
Another tool you can use for this (not Meander) is clojure.walk/prewalk-replace
:
(let [bindings {::name "Mark"
::state "California"}
template ["here is some data for"
::name
{:name ::name
:state ::state}]]
(clojure.walk/prewalk-replace bindings template))
;; =>
["here is some data for" "Mark" {:name "Mark", :state "California"}]
Of course, if you don’t want something as blunt as prewalk-replace
you can accomplish the same thing with Meander and your own custom rules for more control:
(let [bindings {::name "Mark"
::state "California"}
template ["here is some data for"
::name
{:name ::name
:state ::state}]]
(m/rewrite [template bindings]
[[!xs ...] ?bindings]
[(m/cata [!xs ?bindings]) ...]
[{?k ?v & ?rest} ?bindings]
{(m/cata [?k ?bindings]) (m/cata [?v ?bindings]) & (m/cata [?rest ?bindings])}
[?x {?x ?v :as ?bindings}]
(m/cata [?v ?bindings])
?x
?x))
;; =>
["here is some data for" "Mark" {:state "California", :name "Mark"}]