Run embedded code from a different namespace
clojure, namespaces
Solution
Try this one:
(defmacro with-ns [[namespace symbols] & body]
`(do (use '[~namespace :only ~symbols])
(let [result# (do ~@body)]
(doseq [sym# (map #(:name (meta (val %)))
(filter #(= (name '~namespace)
(str (:ns (meta (val %)))))
(ns-refers *ns*)))]
(ns-unmap *ns* sym#))
result#)))
(with-ns [clojure.string [split upper-case]]
(split (upper-case "it works!") #" "))
-> ["IT" "WORKS!"]
After work it removes used symbols from current ns.
Problem
I often want to run a small snippet of code in another namespace - perhaps a copy/pasted snippet of DSL code for example, and I'd like to avoid having to either: - Add a bunch of `use` clauses to my current namespace declaration. This makes the ns declaration messy, adds extra maintenance work and sometimes risks name clashes. - Add `require` clauses and be forced to add a namespace qualifier or alias to everything. Now my DSL code is much messier. Ideally I'd prefer to be able to do something like: ``` (with-ns my.namespace (foo bar baz)) ``` Where `foo`, `bar` might be symbols within `my.namespace`, but `baz` is a symbol in the current (enclosing) namespace. So the code is running in something like a "local" namespace that "uses" my-namespace within its scope but otherwise doesn't affect the surrounding namespace. Is there a standard/better way to do this? Or is this a crazy thing to want to do?