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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to