Skip to content

Instantly share code, notes, and snippets.

@danlentz
Forked from flyingmachine/defnpd.clj
Created September 9, 2013 02:06
Show Gist options
  • Save danlentz/6490669 to your computer and use it in GitHub Desktop.
Save danlentz/6490669 to your computer and use it in GitHub Desktop.
defn with default positional arguments
(defmacro defnpd
;; defn with default positional arguments
[name args & body]
(let [unpack-defaults
(fn [args]
(let [[undefaulted defaulted] (split-with (comp not vector?) args)
argcount (count args)]
(loop [defaulted defaulted
argset {:argnames (into [] undefaulted)
:application (into [] (concat undefaulted (map second defaulted)))}
unpacked-args [argset]
position (count undefaulted)]
(if (empty? defaulted)
unpacked-args
(let [argname (ffirst defaulted)
new-argset {:argnames (conj (:argnames argset) argname)
:application (assoc (:application argset) position argname)}]
(recur (rest defaulted) new-argset (conj unpacked-args new-argset) (inc position)))))))
unpacked-args (unpack-defaults args)]
`(defn ~name
(~(:argnames (last unpacked-args))
~@body)
~@(map #(list (:argnames %)
`(~name ~@(:application %)))
(drop-last unpacked-args)))))
;; Midje testing
(fact "defnpd creates positional defaults"
(defnpd test-defnpd
[a b [c 1] [d 1]]
(+ a b c d))
(test-defnpd 2 2) => 6
(test-defnpd 2 2 2) => 7
(test-defnpd 2 2 2 2) => 8)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment