我认为对于任何撰写defn
的人来说,有什么可以成为一个漂亮的工具 - 就像clojure.tools.macro库中的宏:name-with-attributes
函数一样。文档字符串说:
用于宏定义。 处理要定义的名称的可选文档字符串和属性映射 在宏参数列表中。如果第一个宏参数是一个字符串, 它作为docstring添加到name并从宏参数中删除 名单。如果之后第一个宏参数是一个映射,则其条目为 添加到名称的元数据映射,并从中删除地图 宏参数列表。返回值是包含名称的向量 使用扩展的元数据映射和未处理的宏列表 参数。
但我似乎无法找到在任何地方使用此功能的示例。
那么,我如何使用此函数来定义一个defn2
宏,它应该是包含所有相同功能的clojure.core/defn
的克隆,包括:
答案 0 :(得分:6)
以下是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)))
查看元数据,我们可以看到它已正确附加:
(defn2 ^:private add
"Docstring"
([] :foo)
([a b] {:pre [(= 1 1)]} (+ a b)))
(pprint (meta #'add))
...产率:
{: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"}
使用上面的defn2
创建了一个add
函数,其功能如下:
(add) ; => :foo
(add 1 2) ; => 3