Skip to content

Instantly share code, notes, and snippets.

@flyingmachine
Last active December 18, 2015 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save flyingmachine/5828035 to your computer and use it in GitHub Desktop.
Save flyingmachine/5828035 to your computer and use it in GitHub Desktop.
This macro lets you easily create functions 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