Clojure名称空间管理 - 有没有办法保存和恢复clojure repl名称空间,导入等的状态?

Ale*_*ard 11 state namespaces clojure read-eval-print-loop

Clojure有大量的函数/宏来处理命名空间和java包导入.对于我的(有限的)理解,命名空间的设置可以在clojure过程中被视为状态(repl).

当在REPL会话中迭代地工作时,特别是当(重新)加载源文件时,我发现很容易混淆 - 通常当我在命名空间配置中出错或语法错误时.其他时候我想尝试重构命名空间/别名/引用过滤器,但不能在不重新启动REPL的情况下轻松退出现有的命名空间状态.

例如,我希望能够检查点命名空间配置 - 例如在repl上加载代码主体之后 - 然后在尝试在REPL导入的某些库之后返回到"clean-slate",这样我就可以立即测试一个源文件,该文件作为ns宏的一部分导入该库中已过滤的方法子集.

人们可以推荐保存和恢复命名空间配置的方法吗?

Isa*_*aac 10

我确定这有什么问题,因为我只是在回答这个问题时写的,但我发现自己在我的项目中使用了这个,当然.只是:导入它(将它放在项目中的自己的文件中)并自由地使用它.

(ns world)


(defn save-world
  []
  (let [syms (filter identity (distinct (for [i (ns-map *ns*)] (first i))))]
    (for [i syms]
      (vector i
              (ns-resolve *ns* i)))))

(defn destroy-world-but
  [saved]
  (let [syms (filter identity (distinct (for [i (ns-map *ns*)] (first i))))]
    (for [i syms]
      (if-not (or (= (ns-resolve *ns* i) (ns-resolve *ns* saved))
                  (= (ns-resolve *ns* i) (ns-resolve *ns* 'restore-world))
                  (= (ns-resolve *ns* i) (ns-resolve *ns* '*ns*)))
        (ns-unmap *ns* i)))))

(defn restore-world
  [saved]
  (clojure.core/map
   #(intern *ns* (clojure.core/first %) (clojure.core/second %))
   saved))
Run Code Online (Sandbox Code Playgroud)

首先,保存您的世界状态(您想要返回的状态),如下所示:

(def *save* (save-world))
Run Code Online (Sandbox Code Playgroud)

然后做你想做的任何事 - 实验.当你准备回到以前的状态时:

(destroy-world-but '*save*)
(restore-world *save*)
Run Code Online (Sandbox Code Playgroud)

你应该好好去!

(希望这有效!为我工作 - 如果有问题,请告诉我.我确信有更好的方法可以做到这一点,但这是有效的,这是我今晚有多远.我确定我'我会修改.)


Stu*_*rra 6

这并不总是有效.您可以使用命名空间删除Vars ns-unmap,但其他代码段仍可能包含对这些定义的引用.

Clojure,因为它基于JVM,没有像一些Common Lisp或Scheme实现那样的"内存映像"概念.