如何编写宏自动解析符号

时间:2012-12-27 02:51:38

标签: macros clojure

我总是希望有一种方法可以自动解析符号。例如,如果我在“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)

然后,有一个例外:

CompilerException java.lang.RuntimeException:无法获取宏的值:#'clojure.repl / doc,编译:(NO_SOURCE_PATH:112)

那么,那是为什么?感谢

1 个答案:

答案 0 :(得分:2)

您可以在宏中编译时解析符号,如下所示:

(defmacro call [sym & args]
  (let [f (first (distinct (remove nil? (map #(ns-resolve % sym) (all-ns)))))]
      `(~f ~@args)))