从不同的命名空间运行嵌入式代码

mik*_*era 5 namespaces clojure

我经常想在另一个命名空间中运行一小段代码 - 例如,可能是DSL代码的复制/粘贴代码段,我想避免不得不:

  • use在我当前的命名空间声明中添加一堆子句.这使得ns声明变得混乱,增加了额外的维护工作,有时还会冒名字冲突.
  • 添加require子句并强制为所有内容添加命名空间限定符或别名.现在我的DSL代码更加混乱.

理想情况下,我更愿意做以下事情:

(with-ns my.namespace
  (foo bar baz))
Run Code Online (Sandbox Code Playgroud)

其中foo,bar可能是符号my.namespace,但是baz当前(封闭)命名空间中的符号.因此代码运行在类似"本地"命名空间的东西中,在其范围内"使用"my-namespace但不影响周围的命名空间.

有没有标准/更好的方法来做到这一点?或者这是一件疯狂的事情?

mob*_*yte 4

试试这个:

(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!"]
Run Code Online (Sandbox Code Playgroud)

工作结束后,它会从当前 ns 中删除使用过的符号。