Каков предпочтительный способ перезагрузки функций, определенных в файле Clojure, без перезапуска REPL. Прямо сейчас, чтобы использовать обновленный файл, я должен:
- редактировать
src/foo/bar.clj
- закрыть ответ
- открыть ответ
(load-file "src/foo/bar.clj")
(use 'foo.bar)
Кроме того, (use 'foo.bar :reload-all)
не приводит к требуемому эффекту, который оценивает измененные тела функций и возвращает новые значения, а не ведет себя так, как источник не изменился вообще.
Документация:
(use 'foo.bar :reload-all)
всегда работал хорошо для меня. Кроме того,(load-file)
никогда не должно быть необходимости, если у вас правильно настроен путь к классам. Какой «требуемый эффект» вы не получаете?bar.clj
подробным описанием «требуемого эффекта».(defn f [] 1)
и я изменил ее определение на(defn f [] 2)
, мне казалось, что после того, как я(use 'foo.bar :reload-all)
вызову и вызовуf
функцию, она должна вернуть 2, а не 1. К сожалению, это не работает таким образом для меня и для всех Когда я меняю тело функции, мне нужно перезапустить REPL.:reload
или:reload-all
оба должны работать.Ответы:
Или
(use 'your.namespace :reload)
источник
:reload-all
также должен работать. ОП специально говорит, что это не так, но я думаю, что в среде разработчиков ОП было что-то еще не так, потому что для одного файла два (:reload
и:reload-all
) должны иметь одинаковый эффект. Вот полная команда для:reload-all
:(use 'your.namespace :reload-all)
Это также перезагружает все зависимости.Существует также альтернатива, такая как использование tools.namespace , она довольно эффективна:
источник
(refresh)
похоже, также заставляет REPL забыть о том, что вам нужноclojure.tools.namespace.repl
. Последующие вызовы(refresh)
создадут вам исключение RuntimeException «Не удалось разрешить символ: обновить в этом контексте». Вероятно, лучшее, что можно сделать, это либо либо(require 'your.namespace :reload-all)
, либо, если вы знаете, что хотите много обновить свой REPL для данного проекта, создать:dev
профиль и добавить[clojure.tools.namespace.repl :refer (refresh refresh-all)]
вdev/user.clj
.Перегрузочный Clojure код , используя
(require … :reload)
и:reload-all
является весьма проблематичным :Библиотека clojure.tools.namespace значительно улучшает ситуацию. Он предоставляет функцию простого обновления, которая выполняет интеллектуальную перезагрузку на основе графа зависимостей пространств имен.
К сожалению, повторная загрузка не удастся, если пространство имен, в котором вы ссылались на
refresh
функцию, изменилось. Это связано с тем, что tools.namespace уничтожает текущую версию пространства имен перед загрузкой нового кода.Вы можете использовать полное имя var в качестве обходного пути для этой проблемы, но лично я предпочитаю не вводить это при каждом обновлении. Другая проблема, связанная с вышеизложенным, заключается в том, что после перезагрузки основного пространства имен на стандартные вспомогательные функции REPL (например,
doc
иsource
) больше нет ссылок.Для решения этих проблем я предпочитаю создать фактический исходный файл для пространства имен пользователя, чтобы его можно было надежно перезагрузить. Я положил исходный файл,
~/.lein/src/user.clj
но вы можете разместить в любом месте. Файл должен требовать функцию обновления в объявлении top ns следующим образом:Вы можете настроить профиль пользователя leiningen
~/.lein/profiles.clj
таким образом, чтобы местоположение, в которое вы помещаете файл, было добавлено в путь к классам. Профиль должен выглядеть примерно так:Обратите внимание, что я установил пространство имен пользователя в качестве точки входа при запуске REPL. Это гарантирует, что на вспомогательные функции REPL будут ссылаться в пространстве имен пользователя вместо основного пространства имен вашего приложения. Таким образом, они не потеряются, если вы не измените исходный файл, который мы только что создали.
Надеюсь это поможет!
источник
:source-paths
меня получается#<FileNotFoundException java.io.FileNotFoundException: Could not locate user__init.class or user.clj on classpath: >
, а у меня:resource-paths
все нормально.:resource-paths
, я нахожусь в моем пространстве имен пользователя внутри repl.reload
проблемы. Тогда оказалось, что все, что я думал, работало, больше не было. Может быть, кто-то должен исправить эту ситуацию?Лучший ответ:
Это не только перезагрузит указанное вами пространство имен, но также перезагрузит все пространства имен зависимостей.
Документация:
требовать
источник
lein repl
Coljure 1.7.0 и nREPL 0.3.5. Если вы новичок в Clojure: Пространство имен ('my.namespace
) определяется(ns ...)
вsrc/
.../core.clj
, например.proj.stuff.core
на файловую структуру на диске, напримерsrc/proj/stuff/core.clj
, REPL может найти правильный файл, и вам это не нужноload-file
.Один лайнер, основанный на ответе Папачана:
источник
Я использую это в Lighttable (и удивительном instarepl), но это должно быть полезно в других инструментах разработки. У меня возникла та же проблема со старыми определениями функций и мультиметодами, зависшими после перезагрузок, так что теперь во время разработки вместо объявления пространств имен с помощью:
Я объявляю свои пространства имен следующим образом:
Довольно уродливо, но всякий раз, когда я переоцениваю все пространство имен (Cmd-Shift-Enter в Lighttable, чтобы получить новые результаты instarepl для каждого выражения), оно уничтожает все старые определения и дает мне чистую среду. Меня опускали каждые несколько дней старые определения, прежде чем я начал это делать, и это спасло мое здравомыслие. :)
источник
Попробуйте загрузить файл еще раз?
Если вы используете IDE, обычно есть сочетание клавиш для отправки блока кода в REPL, что позволяет эффективно переопределить связанные функции.
источник
Как только
(use 'foo.bar)
у вас работает, это означает, что у вас есть foo / bar.clj или foo / bar_init.class в вашем CLASSPATH. Bar_init.class будет AOT-скомпилированной версией bar.clj. Если вы это сделаете(use 'foo.bar)
, я не совсем уверен, предпочитает ли Clojure класс над clj или наоборот. Если он предпочитает файлы классов и у вас есть оба файла, тогда ясно, что редактирование файла clj и перезагрузка пространства имен не имеет никакого эффекта.КСТАТИ: Вам не нужно
load-file
перед тем ,use
если ваш CLASSPATH установлен должным образом.Кстати: если вам нужно использовать
load-file
по какой-то причине, то вы можете просто сделать это снова, если вы отредактировали файл.источник