代码之家  ›  专栏  ›  技术社区  ›  Tim Gilbert

帮助我编写一个Clojure宏,它会自动将元数据添加到函数定义中

  •  19
  • Tim Gilbert  · 技术社区  · 17 年前

    我意识到宏俱乐部的第一条规则是不要使用宏,所以下面的问题更像是学习Clojure的练习,而不是其他任何东西(我意识到这不一定是最好的) 使用

    我想写一个简单的宏,它充当正则表达式的包装器 (defn) 宏,并向定义的函数添加一些元数据。所以我想要这样的东西:

    (defn-plus f [x] (inc x))
    

    …扩展到如下内容:

    (defn #^{:special-metadata :fixed-value} f [x] (inc x))
    

    原则上,这对我来说似乎并不难,但我很难确定具体的细节 [args] 以及定义的函数中要正确解析的其他形式。

    clojure-contrib/def 看起来可能有用的包,但很难找到使用它们的示例代码。

    1 回复  |  直到 17 年前
        1
  •  18
  •   amalloy    9 年前

    更新:

    我以前的回答不是很有力。这似乎是一种更简单、更恰当的方法,从 clojure.contrib.def :

    (defmacro defn-plus [name & syms]
      `(defn ~(vary-meta name assoc :some-key :some-value) ~@syms))
    
    user> (defn-plus ^Integer f "Docstring goes here" [x] (inc x))
    #'user/f
    user> (meta #'f)
    {:ns #<Namespace user>, :name f, :file "NO_SOURCE_PATH", :line 1, :arglists ([x]), :doc "Docstring goes here", :some-key :some-value, :tag java.lang.Integer}

    #^{} with-meta Clojure mailing list . 这一切都有点混乱,而且在邮件列表中出现了很多次;另见 here 例如

    注意 def var 你是 def 指向命名var的符号的元数据;我认为,这是上述方法有效的唯一原因。见 DefExpr Compiler.java

    最后,第216页,共页 Programming Clojure 说:

    通常应避免在宏扩展中使用读卡器宏,因为读卡器宏是在宏扩展开始之前在读取时计算的。

    推荐文章