将Clojure宏视为一种功能

pau*_*doo 15 macros clojure

如何使Clojure宏充当函数,所以我可以将它作为参数传递给你?我希望不得不以某种方式包装它.

我不希望包装版本的行为与原始宏完全相同(按名称调用与按值调用的差异),但在少数情况下这不重要.

trp*_*lin 21

如果我正确理解你,你可以将它包装在一个函数中.

考虑将这个(愚蠢的)平方函数实现为宏:

(defmacro square [x]
  (list * x x))
Run Code Online (Sandbox Code Playgroud)

如你所知,直接将它作为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)
Run Code Online (Sandbox Code Playgroud)

但是将它包装在一个函数中就可以了:

user=> (map #(square %) [1 2 3 4 5])
(1 4 9 16 25)
Run Code Online (Sandbox Code Playgroud)

或者(并且更加邪恶),您可以制作另一个宏来进行更通用的包装:

(defmacro make-fn [m] 
  `(fn [& args#] 
    (eval `(~'~m ~@args#))))

user=> (map (make-fn square) [1 2 3 4 5])
(1 4 9 16 25)
Run Code Online (Sandbox Code Playgroud)

我坚持使用正常的函数包装,并跳过最后一次破解!:)

  • 嗯,这对于可变参数宏不起作用:user =>(apply#(或%)[true false false])java.lang.IllegalArgumentException:错误的args(3)传递给:user $ eval3 $ fn(NO_SOURCE_FILE) :0) (3认同)
  • 3分:(1)解决这个例子的最好方法是`(某些身份[true false false])`,(2)如果你知道params的数量并明确表示,那就行了:`( apply#(或%1%2%3)[true false false])`,(3)hacky`make-fn`有效:`(apply(make-fn or)[true false false])` (2认同)

jne*_*ira 5

有一个危险的,已弃用的宏,你不应该使用它.:-P

http://clojure.github.com/clojure-contrib/apply-macro-api.html