我想评估对宏的参数是否是函数。如果是,我想返回未评估的功能。否则返回其他功能。喜欢:
(defmacro func? [function]
(if (fn? function)
function
identity))
((func? "oops") 5) ;=> 5
((func? -) 5) ;=> 5
然而,以上失败是因为未评估的函数尚未真实函数才能使其起作用,所以我必须使用邪恶评估:
(defmacro func? [function]
(if (fn? (eval function))
function
identity))
((func? "oops") 5) ;=> 5
((func? -) 5) ;=> -5
我如何避免在此处使用评估?答案必须是宏。
在我的情况下,宏观上有宏观的原因是,该宏用于许多在我的游戏中被称为多次的功能。宏是输出格式解释器。换句话说,我可以自己写它,但是宏使我的代码更加清洁。如果我使用一个函数而不是这个宏,那将是同样的解释,只需要一次完成一次,每50ms的游戏迭代约60次。希望这样可以澄清而不是蒙上我的处境。
您需要考虑到宏的许多可能的参数,以决定是否是功能。
- 它是符号吗?一个号码?字符串?
- 符号解析为函数的var?
- 在哪个命名空间中,该符号需要解决?
假设在当前名称空间中解决实时的函数,您可以做类似的事情:
(defn test
[]
"result")
(defmacro func?
[f]
(if (and (symbol? f)
(fn? (var-get (ns-resolve *ns* f))))
f
identity))
(func? test)
#object[user$test 0x37c27452 "prisma.server$test@37c27452"]
(func? 4)
#object[clojure.core$identity 0x3a811e64 "clojure.core$identity@3a811e64"]
其中ns-resolve
和var-get
为您提供了适当的函数值的处理(或所有情况的任何值F是解决某物的符号)。
例如,从当前名称空间工作中解析的所有功能,例如:
(:require [some.ns :as other-ns])
(func? other-ns/valid-fn)
=> #object[some.ns$valid-fn 0x7207a00b "some.ns$valid-fn@7207a00b"]
为什么要使用宏?
(defn func? [function]
(if (fn? function)
function
identity))
((func? "oops") 5) ;=> 5
((func? -) 5) ;=> -5
请注意,#(identity %)
只是identity
。