Управление пространством имен Clojure - существует ли способ сохранить и восстановить состояние пространств имен repl Clojure, импорта и т. Д.? - PullRequest
11 голосов
/ 14 августа 2010

Clojure имеет большое количество функций / макросов для работы с пространствами имен и импорта пакетов java. По моему (ограниченному) пониманию, установка пространств имен может рассматриваться как состояние в процессе замыкания (repl).

При итерационной работе в сеансе REPL, особенно когда исходные файлы (пере) загружены, я могу легко запутаться - часто, когда я делаю ошибку или синтаксическую ошибку в конфигурации пространства имен. В других случаях я хочу попробовать рефакторинг пространств имен / псевдонимов / ссылочных фильтров, но не могу легко выйти из существующего состояния пространства имен без перезапуска REPL.

Например, я хотел бы иметь возможность конфигурировать пространство имен контрольных точек, например, после загрузки основной части кода в repl, а затем вернуться к этому «чистому списку» после того, как попробовал какую-то библиотеку, импортированную в REPL что я могу немедленно протестировать исходный файл, который импортирует отфильтрованное подмножество методов в эту библиотеку как часть макроса ns.

Могут ли люди порекомендовать способы сохранения и восстановления конфигурации пространства имен?

Ответы [ 3 ]

10 голосов
/ 14 августа 2010

Я уверен, что что-то неправильно с этим, так как я только что написал это в ответ на этот вопрос, но я вижу себя использующим это в своих проектах, наверняка.Просто: импортируйте его (поместите в отдельный файл в вашем проекте) и используйте его свободно.

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

И вам следует идти!

(Надеюсь, это работает! У меня сработало, пожалуйста, дайте мне знатьесли есть проблема. Я уверен, что есть и лучший способ сделать это, но это работает, и это то, как далеко я продвинулся сегодня вечером. Я уверен, что пересмотрю.)

6 голосов
/ 14 августа 2010

Это не всегда работает.Вы можете удалить Vars из пространства имен с помощью ns-unmap, но другие фрагменты кода могут по-прежнему содержать ссылки на эти определения.

Clojure, поскольку он основан на JVM, не имеет понятия «образ памяти»как некоторые реализации Common Lisp или Scheme.

1 голос
/ 03 апреля 2011

DMTCP может выполнить эту работу неуклюже.Google на DMTCP: распределенная многопоточная проверка CheckPointing.Я использую его для создания контрольных точек интерактивных программ OCaml.

...