如何让Clojure宏充当函数,所以我可以将其作为参数传递给它?我希望不得不以某种方式包装它。将Clojure宏看作函数
我不希望包装版本的行为与原始宏完全一样(名称与值的调用不同),但在少数情况下这很重要。
如何让Clojure宏充当函数,所以我可以将其作为参数传递给它?我希望不得不以某种方式包装它。将Clojure宏看作函数
我不希望包装版本的行为与原始宏完全一样(名称与值的调用不同),但在少数情况下这很重要。
如果我正确理解你,你可以把它包装在一个函数。
考虑这个(傻)实现平方功能的宏:
(defmacro square [x]
(list * x x))
直接把它当作一个ARG将无法正常工作,如你所知:
user=> (map square [1 2 3 4 5])
java.lang.Exception: Can't take value of a macro: #'user/square (NO_SOURCE_FILE:8)
但其包装在一个函数将做的伎俩:
user=> (map #(square %) [1 2 3 4 5])
(1 4 9 16 25)
或者(更恶意地),你可以做另一个宏做一个更通用的包装:
(defmacro make-fn [m]
`(fn [& args#]
(eval `(~'~m [email protected]#))))
user=> (map (make-fn square) [1 2 3 4 5])
(1 4 9 16 25)
我会坚持正常的功能包装,并跳过这最后的黑客! :)
有一个危险的,不推荐使用的宏,你不应该使用它。 :-P
http://clojure.github.com/clojure-contrib/apply-macro-api.html
嗯,这给了我一个堆栈溢出,当我试图用Clojure 1.2这个例子:(?应用宏或[真虚假])) – pauldoo 2011-04-05 07:50:36
唉这是真的,问题是私有函数价差apply-macro ns:它是一个陈旧clojure.core的副本,如果你用实际版本替换它[黑客工程](https://gist.github.com/986321) – jneira 2011-05-23 06:29:39
diff是好奇的rest [1]) - >(),(next [1]) - > nil。第一个与零?作为防止谓词停止递归引发了stackoverflow。 – jneira 2011-05-23 06:32:16
对于疯狂的宏make-fn,下面的那个怎么样? 它应该工作得很好,并且希望更容易理解。
(defmacro make-fn [m]
`(fn [& args#]
(eval
(cons '~m args#))))
嗯,这不适用于可变宏: user =>(应用#(或%)[true false false]) java.lang.IllegalArgumentException:错误的参数数量(3)传递给:user $ eval3 $ fn(NO_SOURCE_FILE:0) – pauldoo 2011-04-05 07:32:18
3分:(1)解决这个例子的最好方法是'(某种身份[true false false])',(2)如果你知道params的数量并且明确表示它, (应用#(或%1%2%3)[true false false]),(3)hacky'make-fn'工作:'(apply(make-fn or)[true false假])' – trptcolin 2011-04-05 13:06:20