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)
你应该好好去!
(希望这有效!为我工作 - 如果有问题,请告诉我.我确信有更好的方法可以做到这一点,但这是有效的,这是我今晚有多远.我确定我'我会修改.)
这并不总是有效.您可以使用命名空间删除Vars ns-unmap,但其他代码段仍可能包含对这些定义的引用.
Clojure,因为它基于JVM,没有像一些Common Lisp或Scheme实现那样的"内存映像"概念.