Reputation: 783
I'm always fancy that there is a method to resolve symbols automatically. For example, if I am in the "user" namespace and have not "used" symbols in the `clojure.string' namespace, instead of:
(clojure.string/split "a-b-c" #"-")
I want to write as this:
(call split "a-b-c" #"-")
I have simply implemented a `call' macro as this:
(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))))))
the following tests are always ok:
(call list 'a 'b)
(call apropos "list")
(call doc list)
(call doc clojure.string/split)
the problem happens when I pass a macro as the argument of `doc':
(call doc clojure.repl/doc)
then, there is a exception:
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc, compiling:(NO_SOURCE_PATH:112)
So, that's why? thanks
Upvotes: 3
Views: 678
Reputation: 33637
You can resolve the symbol at compile time in the macro like this:
(defmacro call [sym & args]
(let [f (first (distinct (remove nil? (map #(ns-resolve % sym) (all-ns)))))]
`(~f ~@args)))
Upvotes: 2