Thursday, 15 January 2015

clojure - DSL syntax with optional parameters -



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