【问题标题】:Clojure namespace management - Is there a way to save and restore the state of clojure repl namespaces, imports etc.?Clojure 命名空间管理 - 有没有办法保存和恢复 clojure repl 命名空间、导入等的状态?
【发布时间】:2011-03-29 15:58:51
【问题描述】:

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

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

例如,我希望能够检查点命名空间配置 - 例如在 repl 加载主体代码之后 - 然后在尝试在 REPL 导入的一些库后返回到那个“干净的石板”,所以我可以立即测试一个源文件,该文件将该库中过滤的方法子集作为 ns 宏的一部分导入。

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

【问题讨论】:

  • 这听起来像是许多 Common Lisp 实现所具备的 save-world 功能。
  • 这应该是可能的,使用 (clojure.lang.Namespace/all) 和 .getMappings,但我找不到任何迹象表明有人已经这样做了。

标签: namespaces clojure state read-eval-print-loop


【解决方案1】:

我确定这有一些问题,因为我只是在回答这个问题时写了它,但我看到自己在我的项目中使用它,这是肯定的。只需 :import 即可(将其放在项目中自己的文件中)并随意使用它。

(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))

首先,像这样保存你的世界的状态(你想回到的那个):

(def *save* (save-world))

然后做任何你想做的事——实验。当您准备好回到以前的状态时:

(destroy-world-but '*save*)
(restore-world *save*)

你应该很高兴!

(希望这行得通!对我有用——如果有问题请告诉我。我相信也有更好的方法来做到这一点,但这行得通,而且我今晚能走多远。我是当然我会修改。)

【讨论】:

    【解决方案2】:

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

    Clojure,因为它基于 JVM,所以没有像某些 Common Lisp 或 Scheme 实现那样的“内存映像”的概念。

    【讨论】:

    • 警告做得好。因此,例如,如果我试图保存和恢复一个复杂的长时间运行的应用程序的状态,我可能会遇到很多麻烦。但是对于在单个 repl 会话中需要/别名的函数的简单用例,我怀疑我可能可以做如下 Issac 所示的事情。
    【解决方案3】:

    DMTCP 可能以笨拙的方式完成这项工作。 DMTCP 上的 Google:分布式多线程检查点。我用它来检查交互式 OCaml 程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多