Skip to content

Instantly share code, notes, and snippets.

@noprompt
Created October 1, 2015 18:07
Show Gist options
  • Save noprompt/a93ac4490cc22b4691ac to your computer and use it in GitHub Desktop.
Save noprompt/a93ac4490cc22b4691ac to your computer and use it in GitHub Desktop.
(letfn [(variadic? [arglist]
(boolean (some #{'&} arglist)))
(arglistc [arglist]
(if (variadic? arglist)
Double/POSITIVE_INFINITY
(count arglist)))
(partial-arglists [arglists argc]
(drop-while
(fn [arglist]
(<= (arglistc arglist) argc))
arglists))]
(defmacro defpartial [sym f & args]
(let [v (cond
(var? f)
fn
(symbol? f)
(resolve f)
:else
(throw (IllegalArgumentException. "f must be a symbol or a var")))
arglists (:arglists (meta v))
argc (count args)
partial-arglists (partial-arglists arglists argc)
partial-arglists (if (variadic? (first partial-arglists))
(let [arglist (first partial-arglists)
[positional-args rest-args] (split-with (complement #{'&}) arglist)
positional-args (drop argc positional-args)]
(list (vec (concat positional-args rest-args))))
partial-arglists)
fn-specs (for [arglist partial-arglists]
`(~arglist
~(if (variadic? arglist)
`(apply ~v ~@args ~@(remove #{'&} arglist))
`(~v ~@args ~@arglist))))]
`(defn sym ~@fn-specs))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment