我一直幻想有一种方法可以自动解析符号。例如,如果我位于“user”命名空间中,并且在“clojure.string”命名空间中没有“使用”符号,则:
(clojure.string/split "a-b-c" #"-")
我想这样写:
(call split "a-b-c" #"-")
我简单地实现了一个“call”宏,如下所示:
(defmacro call [sym & args]
`(let [fn# (first (distinct (remove nil? (map #(ns-resolve % '~sym) (all-ns)))))]
(if-not ((meta fn#) :macro)
(fn# ~@args)
(eval (list fn# ~@(map #(list 'quote %) args))))))
以下测试总是没问题的:
(call list 'a 'b)
(call apropos "list")
(call doc list)
(call doc clojure.string/split)
当我传递一个宏作为“doc”的参数时,就会出现问题:
(call doc clojure.repl/doc)
那么,有一个异常(exception):
CompilerException java.lang.RuntimeException:无法获取宏的值:#'clojure.repl/doc,编译:(NO_SOURCE_PATH:112)
所以,这就是为什么?谢谢
最佳答案
您可以在编译时在宏中解析符号,如下所示:
(defmacro call [sym & args]
(let [f (first (distinct (remove nil? (map #(ns-resolve % sym) (all-ns)))))]
`(~f ~@args)))
关于macros - 如何编写宏自动解析符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14048811/