我如何使用`clojure.tools.macro / name-with-attributes`?

时间:2014-08-25 02:11:27

标签: macros clojure

我认为对于任何撰写defn的人来说,有什么可以成为一个漂亮的工具 - 就像clojure.tools.macro库中的宏:name-with-attributes函数一样。文档字符串说:

  

用于宏定义。      处理要定义的名称的可选文档字符串和属性映射      在宏参数列表中。如果第一个宏参数是一个字符串,      它作为docstring添加到name并从宏参数中删除      名单。如果之后第一个宏参数是一个映射,则其条目为      添加到名称的元数据映射,并从中删除地图      宏参数列表。返回值是包含名称的向量      使用扩展的元数据映射和未处理的宏列表      参数。

但我似乎无法找到在任何地方使用此功能的示例。

那么,我如何使用此函数来定义一个defn2宏,它应该是包含所有相同功能的clojure.core/defn的克隆,包括:

  • 文档字符串
  • 属性地图
  • 先决条件
  • 多arities

1 个答案:

答案 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