clojure - DSL syntax with optional parameters -
i'm trying handle next dsl:
(simple-query (is :category "car/audi/80") (is :price 15000))
that went quite smooth, added 1 more thing - options passed query:
(simple-query {:page 1 :limit 100} (is :category "car/audi/80") (is :price 15000))
and have problem how handle case in civilized way. can see simple-query
may hash-map first element (followed long list of criteria) or may have no hash-mapped options @ all. moreover, have defaults default set of options in case when (or all) of them not provided explicite in query.
this figured out:
(def ^{:dynamic true} *defaults* {:page 1 :limit 50}) (defn simple-query [& body] (let [opts (first body) [params criteria] (if (map? opts) [(merge *defaults* opts) (rest body)] [*defaults* body])] (execute-query params criteria)))
i sense it's kind of messy. thought how simplify construction?
to solve problem in own code, have handy function i'd meet... take-when
.
user> (defn take-when [pred [x & more :as fail]] (if (pred x) [x more] [nil fail])) #'user/take-when user> (take-when map? [{:foo :bar} 1 2 3]) [{:foo :bar} (1 2 3)] user> (take-when map? [1 2 3]) [nil [1 2 3]]
so can utilize implement parser optional map first argument...
user> (defn maybe-first-map [& args] (let [defaults {:foo :bar} [maybe-map args] (take-when map? args) options (merge defaults maybe-map)] ... ;; work ))
so far i'm concerned, proposed solution more or less spot on, clean factoring out parser grabbing options map (here take-when
helper) , factoring out merging of defaults own binding statement.
as general matter, using dynamic var storing configurations antipattern due potential missbehavior when evaluated lazily.
clojure dsl
No comments:
Post a Comment