Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Lisp 帮助我编写一个Clojure宏,它会自动将元数据添加到函数定义中_Lisp_Clojure_Macros_Defn - Fatal编程技术网

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

Lisp 帮助我编写一个Clojure宏,它会自动将元数据添加到函数定义中,lisp,clojure,macros,defn,Lisp,Clojure,Macros,Defn,我意识到宏俱乐部的第一条规则是不要使用宏,因此下面的问题更像是学习Clojure的练习,而不是其他任何东西(我意识到这不一定是宏的最佳使用) 我想编写一个简单的宏,它充当常规(defn)宏的包装器,最后向定义的函数添加一些元数据。所以我想要这样的东西: (defn-plus f [x] (inc x)) (defn #^{:special-metadata :fixed-value} f [x] (inc x)) …扩展到如下内容: (defn-plus f [x] (inc x)) (d

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

我想编写一个简单的宏,它充当常规
(defn)
宏的包装器,最后向定义的函数添加一些元数据。所以我想要这样的东西:

(defn-plus f [x] (inc x))
(defn #^{:special-metadata :fixed-value} f [x] (inc x))
…扩展到如下内容:

(defn-plus f [x] (inc x))
(defn #^{:special-metadata :fixed-value} f [x] (inc x))
原则上,这对我来说并不难,但我很难确定正确解析定义函数中的
[args]
和其他形式的细节


作为奖励,如果可能的话,我希望宏能够处理所有不同形式的defn(即,有或没有docstring、多个arity定义等)。我在软件包中看到了一些可能有用的东西,但很难找到使用它们的示例代码。

更新:

我以前的回答不是很有力。这似乎是一种更简单、更恰当的方法,从
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} (定义宏定义加上[名称和符号] `(defn~(vary meta name assoc:some key:some value)~@syms)) 用户>(defn加上^f整数“Docstring在此”[x](inc x)) #'用户/f 用户>(元) {:ns#,:name f,:file“NO_SOURCE_PATH”,:第1行,:arglist([x]),:doc“Docstring goes here”,:some key:some value,:tag java.lang.Integer}
#^{}
和带有meta的
不是一回事。有关它们之间差异的解释,请参见Rich关于。这一切都有点混乱,而且在邮件列表中出现了很多次;另见示例

请注意,
def
是一种特殊形式,与该语言的其他部分相比,它处理元数据有点奇怪。它将
var
您要
def
的元数据设置为命名var的符号的元数据;我认为,这是上述方法有效的唯一原因。如果您想了解所有内容,请参阅Clojure源代码中
Compiler.java
中的
DefExpr

最后,第216页说:

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


好的介绍。。。主要的道具。为什么不使用宏呢?你在考虑C预处理器吗?很有趣!但有没有一种方法可以更有效地实现这一点?在
do
中包装
defn
,然后破坏性地修改其元数据对我来说似乎有点奇怪。同样,我在
defmacro
内部使用
#^{:k:v}
语法的实验到目前为止都是彻底失败的……做任何类型的
def
都不是一件很实用的事情,因为它破坏性地改变了全局调度表的状态但你是对的,我已经更新了我的答案。我之前的回答是删除
def
通常使用的#^Integer标记元数据。谢谢,这更容易理解,而且这些链接看起来非常有用,尽管我仍然有点困惑(macroexpand-1'(defn plus foo[bar](baz)))为什么不显示with meta标记。试试(设置!打印meta true)然后看一下宏展开。您将看到元数据已应用于命名函数的符号<在宏返回之前,在宏体中执行带meta的code>
。请注意,它在宏中未被引用。