Skip to content

Instantly share code, notes, and snippets.

@didibus
Last active November 3, 2018 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save didibus/3f51d2168635858c8a0854d25689bf9a to your computer and use it in GitHub Desktop.
Save didibus/3f51d2168635858c8a0854d25689bf9a to your computer and use it in GitHub Desktop.
Clojure macro to define strict keyword argument functions
(defmacro defnk
[name & fdecl]
(let [doc-string? (when (string? (first fdecl))
(first fdecl))
fdecl (if (string? (first fdecl))
(next fdecl)
fdecl)
attr-map? (when (map? (first fdecl))
(first fdecl))
fdecl (if (map? (first fdecl))
(next fdecl)
fdecl)
params (first fdecl)
m (gensym)
params* [{:keys params :as m}]
fdecl (next fdecl)
prepost-map? (if (map? (first fdecl))
(first fdecl)
{})
fdecl (if (map? (first fdecl))
(next fdecl)
fdecl)
body fdecl]
`(defn ~name
~@(if doc-string? [doc-string?] [])
~@(if attr-map? [attr-map?] [])
~params*
~(merge-with (comp vec concat)
prepost-map?
{:pre [`(every? some? ~params)
`(= ~(count params) (count ~m))]})
~@body)))
@didibus
Copy link
Author

didibus commented Nov 3, 2018

It is strict in that additional key arguments throw an error at call site, and missing keys throw an error at call site.

@didibus
Copy link
Author

didibus commented Nov 3, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment