如何测试clojure宏中未评估的功能



我想评估对宏的参数是否是函数。如果是,我想返回未评估的功能。否则返回其他功能。喜欢:

(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次。希望这样可以澄清而不是蒙上我的处境。

您需要考虑到宏的许多可能的参数,以决定是否是功能。

  1. 它是符号吗?一个号码?字符串?
  2. 符号解析为函数的var?
  3. 在哪个命名空间中,该符号需要解决?

假设在当前名称空间中解决实时的函数,您可以做类似的事情:

(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-resolvevar-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

最新更新