Clojure: Generating functions from template -
i have following code generic conversion library:
(defn using-format [format] {:format format}) (defn- parse-date [str format] (.parse (java.text.simpledateformat. format) str)) (defn string-to-date ([str] (string-to-date str (using-format "yyyy-mm-dd"))) ([str conversion-params] (parse-date str (:format (merge (using-format "yyyy-mm-dd") conversion-params)))))
i need able call this:
(string-to-date "2011-02-17") (string-to-date "2/17/2011" (using-format "m/d/yyyy")) (string-to-date "2/17/2011" {})
the third case problematic: map not contain key :format
critical function. that's why merge
default value.
i need have dozen of similar functions conversions between other types. there more elegant way not require me copy-paste, use merge
etc. in every single function?
ideally, looking (macro?):
(defn string-to-date (wrap (fn [str conversion-params] (parse-date str (:format conversion-params))) ; implementation {:format "yyyy-mm-dd"})) ; default conversion-params
... produce overloaded function (unary , binary), binary having merge
in first example.
so define little more strictly, want create macro creates converter functions. converter function function 2 arities, 1 argument , 2 arguments. first argument converter function object converted. second argument map of options, somehow affect conversion (like format string in example.)
a default parameter map can specified. when called 1 argument, converter function use default parameter map. when called 2 arguments, converter function merge default parameter map passed in parameter map, such passed in parameters override defaults if exist.
let's call macro def-converter. def converter take 3 arguments, first name of function created. second anonymous function of 2 arguments implements two-arity converter, without default parm merging. third argument default parm map.
something work:
(defmacro def-converter [converter-name converter-fn default-params] (defn ~converter-name ([to-convert#] (let [default-params# ~(eval default-params)] (~converter-fn to-convert# default-params#))) ([to-convert# params#] (let [default-params# ~(eval default-params)] (~converter-fn to-convert# (merge default-params# params#))))))
then can use like:
(def-converter string-to-date (fn [to-convert conversion-params] (parse-date to-convert conversion-params)) (using-format "yyyy-mm-dd"))
but have make change 1 of helper functions:
(defn- parse-date [str params] (.parse (java.text.simpledateformat. (:format params)) str))
this because macro needs general enough handle arbitrary maps of parameters, can't count on. there ways around it, can't think of 1 offhand that's not messier pushing off onto helper function (or anonymous function needs passed def-converter).
Comments
Post a Comment