I see what promises to be a nifty tool for anybody writing defn
-like macros in the clojure.tools.macro library: the name-with-attributes
function. The docstring says:
To be used in macro definitions. Handles optional docstrings and attribute maps for a name to be defined in a list of macro arguments. If the first macro argument is a string, it is added as a docstring to name and removed from the macro argument list. If afterwards the first macro argument is a map, its entries are added to the name's metadata map and the map is removed from the macro argument list. The return value is a vector containing the name with its extended metadata map and the list of unprocessed macro arguments.
But I can't seem to find an example that uses this function anywhere.
So, how can I use this function to define, say, a defn2
macro, which should be a clone of clojure.core/defn
that contains all the same features, including:
Here is defn2
:
(require '[clojure.tools.macro :as ctm])
(defmacro defn2
"A clone of `defn`."
[symb & defn-args]
(let [[symb body] (ctm/name-with-attributes symb defn-args)]
`(defn ~symb ~@body)))
Looking at the metadata we can see that it gets properly attached:
(defn2 ^:private add
"Docstring"
([] :foo)
([a b] {:pre [(= 1 1)]} (+ a b)))
(pprint (meta #'add))
...yields:
{:arglists ([] [a b]),
:ns #<Namespace user>,
:name add,
:column 1,
:private true,
:doc "Docstring",
:line 1,
:file
"/private/var/folders/30/v73zyld1359d7jb2xtlc_kjm0000gn/T/form-init8938188655190399857.clj"}
Using defn2
above created an add
function that works like so:
(add) ; => :foo
(add 1 2) ; => 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With