Jaki jest preferowany sposób ponownego ładowania funkcji zdefiniowanych w pliku Clojure bez konieczności ponownego uruchamiania REPL. W tej chwili, aby skorzystać ze zaktualizowanego pliku, muszę:
- edytować
src/foo/bar.clj
- zamknij REPL
- otwórz REPL
(load-file "src/foo/bar.clj")
(use 'foo.bar)
Ponadto (use 'foo.bar :reload-all)
nie daje wymaganego efektu, który polega na ocenie zmodyfikowanych treści funkcji i zwróceniu nowych wartości, zamiast zachowywać się, jakby źródło w ogóle się nie zmieniło.
Dokumentacja:
clojure
reload
read-eval-print-loop
leiningen
pkaleta
źródło
źródło
(use 'foo.bar :reload-all)
zawsze działało dobrze dla mnie. Ponadto(load-file)
nie powinno być nigdy konieczne, jeśli masz prawidłowo skonfigurowaną ścieżkę klas. Jaki jest „wymagany efekt”, którego nie osiągasz?bar.clj
opisującą „wymagany efekt”.(defn f [] 1)
i zmieniłem jej definicję na(defn f [] 2)
, wydawało mi się, że po wydaniu(use 'foo.bar :reload-all)
i wywołaniuf
funkcji powinna zwrócić 2, a nie 1. Niestety nie działa tak dla mnie i dla wszystkich gdy zmieniam korpus funkcji muszę ponownie uruchomić REPL.:reload
lub:reload-all
oba powinny działać.Odpowiedzi:
Lub
(use 'your.namespace :reload)
źródło
:reload-all
powinien również działać. OP wyraźnie mówi, że tak nie jest, ale myślę, że w środowisku programistycznym OP było coś nie tak, ponieważ w przypadku jednego pliku te dwa (:reload
i:reload-all
) powinny mieć ten sam efekt. Oto pełne polecenie:reload-all
:(use 'your.namespace :reload-all)
To również przeładowuje wszystkie zależności.Istnieje również alternatywa, taka jak użycie tools.namespace , jest całkiem wydajna:
źródło
(refresh)
wydaje się również powodować, że REPL zapomina, że jest to wymaganeclojure.tools.namespace.repl
. Kolejne wywołania wywołania wywołania(refresh)
RuntimeException „Nie można rozpoznać symbolu: odśwież w tym kontekście”. Prawdopodobnie najlepszą rzeczą do zrobienia jest jedno(require 'your.namespace :reload-all)
lub drugie , lub, jeśli wiesz, że będziesz chciał często odświeżać swoją REPL dla danego projektu, utwórz:dev
profil i dodaj[clojure.tools.namespace.repl :refer (refresh refresh-all)]
do niegodev/user.clj
.Ponowne ładowanie kodu Clojure przy użyciu
(require … :reload)
i:reload-all
jest bardzo problematyczne :Biblioteka clojure.tools.namespace znacznie poprawia sytuację. Zapewnia łatwą funkcję odświeżania, która wykonuje inteligentne ponowne ładowanie w oparciu o wykres zależności przestrzeni nazw.
Niestety ponowne załadowanie nie powiedzie się, jeśli przestrzeń nazw, w której odwołujesz się do
refresh
funkcji, ulegnie zmianie. Wynika to z faktu, że tools.namespace niszczy aktualną wersję przestrzeni nazw przed załadowaniem nowego kodu.Możesz użyć w pełni kwalifikowanej nazwy var jako obejścia tego problemu, ale osobiście wolę nie wpisywać tego przy każdym odświeżaniu. Innym problemem związanym z powyższym jest to, że po przeładowaniu głównej przestrzeni nazw nie ma tam odwołań do standardowych funkcji pomocniczych REPL (takich jak
doc
isource
).Aby rozwiązać te problemy, wolę utworzyć rzeczywisty plik źródłowy dla przestrzeni nazw użytkownika, aby można go było niezawodnie ponownie załadować. Umieściłem plik źródłowy,
~/.lein/src/user.clj
ale możesz go umieścić w dowolnym miejscu. Plik powinien wymagać funkcji odświeżania w górnej deklaracji ns w następujący sposób:Możesz skonfigurować profil użytkownika leiningen w
~/.lein/profiles.clj
tak, aby lokalizacja, w której umieściłeś plik, była dodawana do ścieżki klasy. Profil powinien wyglądać mniej więcej tak:Zauważ, że ustawiłem przestrzeń nazw użytkownika jako punkt wejścia podczas uruchamiania REPL. Gwarantuje to, że do funkcji pomocniczych REPL będą odwoływać się przestrzeń nazw użytkownika, a nie główna przestrzeń nazw aplikacji. W ten sposób nie zgubią się, chyba że zmienisz plik źródłowy, który właśnie utworzyliśmy.
Mam nadzieję że to pomoże!
źródło
:source-paths
dostaję#<FileNotFoundException java.io.FileNotFoundException: Could not locate user__init.class or user.clj on classpath: >
, podczas gdy ze:resource-paths
wszystkim jest w porządku.:resource-paths
, jestem w mojej przestrzeni nazw użytkownika wewnątrz repl.reload
problemu. Potem okazało się, że wszystko, o czym myślałem, że działa, już nie działa. Może ktoś powinien naprawić tę sytuację?Najlepsza odpowiedź to:
Spowoduje to nie tylko ponowne załadowanie określonej przestrzeni nazw, ale także przeładuje wszystkie przestrzenie nazw zależności.
Dokumentacja:
wymagać
źródło
lein repl
Coljure 1.7.0 i nREPL 0.3.5. Jeśli nie masz doświadczenia z clojure: przestrzeń nazw ('my.namespace
) jest zdefiniowana na przykład za pomocą(ns ...)
insrc/
..../core.clj
proj.stuff.core
odzwierciedla strukturę plików na dyskusrc/proj/stuff/core.clj
, taka jak REPL może zlokalizować właściwy plik, którego nie potrzebujeszload-file
.Jedna linijka oparta na odpowiedzi Papachana:
źródło
Używam tego w Lighttable (i niesamowitym instarepl), ale powinno to być przydatne w innych narzędziach programistycznych. Miałem ten sam problem ze starymi definicjami funkcji i multimetod, które kręciły się po przeładowaniach, więc teraz podczas programowania zamiast deklarować przestrzenie nazw za pomocą:
Deklaruję moje przestrzenie nazw w następujący sposób:
Dość brzydkie, ale ilekroć ponownie oceniam całą przestrzeń nazw (Cmd-Shift-Enter w Lighttable, aby uzyskać nowe wyniki instarepl dla każdego wyrażenia), usuwa wszystkie stare definicje i zapewnia mi czyste środowisko. Co kilka dni potykały mnie stare definicje, zanim zacząłem to robić, co uratowało mi zdrowie psychiczne. :)
źródło
Spróbuj ponownie załadować plik?
Jeśli używasz IDE, zwykle istnieje skrót klawiaturowy do wysyłania bloku kodu do REPL, co skutecznie definiuje powiązane funkcje.
źródło
Gdy tylko
(use 'foo.bar)
zadziała, oznacza to, że masz foo / bar.clj lub foo / bar_init.class na swojej CLASSPATH. Bar_init.class byłby skompilowaną przez AOT wersją bar.clj. Jeśli tak(use 'foo.bar)
, nie jestem do końca pewien, czy Clojure woli klasę niż clj, czy na odwrót. Jeśli wolałby pliki klas i masz oba pliki, jasne jest, że edycja pliku clj, a następnie ponowne załadowanie przestrzeni nazw nie ma żadnego efektu.BTW: Nie musisz tego robić
load-file
przed,use
jeśli CLASSPATH jest ustawiony poprawnie.BTW2: Jeśli chcesz użyć
load-file
z jakiegoś powodu, możesz po prostu zrobić to ponownie, jeśli edytowałeś plik.źródło