I'd like to propose different implementation of defnk, attached below.
Defnk2 translates keyword arguments to positional arguments at compile
time, and is therefore about 36x faster on my machine.
(defn expand-keyword-call [name pos kw-defaults args]
(if (< (count args) (count pos))
(throw (Exception. "Too few arguments to " name)))
`(~(symbol (str name "*")) ~@(take (count pos) args)
~@(loop [;; current keyword args left to process
kwargs (drop (count pos) args)
;; current keyword values
kwvals (apply hash-map kw-defaults)]
(cond (= (count kwargs) 0)
(map #(kwvals %) (take-nth 2 kw-defaults))
(not (contains? kwvals (first kwargs)))
(throw (Exception. (str "Unknown keyword argument to "
name ": " (first kwargs))))
(= (count kwargs) 1)
(throw (Exception. (str "No value for keyword argument
" (first kwargs) " in call to " name)))
true
(recur (drop 2 kwargs)
(assoc kwvals (first kwargs) (second
kwargs)))))))
(defmacro defnk2 [name args & body]
(let [ [pos kwvals] (split-with symbol? args)]
`(do
(defn ~(symbol (str name "*")) ~(vec (concat pos (map #(symbol
(.getName %)) (take-nth 2 kwvals))))
~@body)
(defmacro
~name [& args#]
(expand-keyword-call '~name '~pos '~kwvals args#))
(.setMeta #'~name (assoc (meta #'~name) :arglists
'(~args) )))))
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en