Kullanarak Clojure kod yeniden yüklenmesi (require … :reload)
ve :reload-all
bir çok sorunlu :
Birbirine bağlı iki ad alanını değiştirirseniz, derleme hatalarını önlemek için bunları doğru sırada yeniden yüklemeyi unutmayın.
Tanımları bir kaynak dosyadan kaldırır ve daha sonra yeniden yüklerseniz, bu tanımlar bellekte de kullanılabilir. Diğer kodlar bu tanımlara bağlıysa, çalışmaya devam eder, ancak JVM'yi bir sonraki başlatışınızda bozulur.
Yeniden yüklenen ad alanı içeriyorsa defmulti
, ilişkili tüm defmethod
ifadeleri de yeniden yüklemeniz gerekir .
Yeniden yüklenen ad alanı içeriyorsa defprotocol
, bu protokolü uygulayan tüm kayıtları veya türleri yeniden yüklemeniz ve bu kayıtların / türlerin mevcut örneklerini yeni örneklerle değiştirmeniz gerekir.
Yeniden yüklenen ad alanı makro içeriyorsa, bu makroları kullanan tüm ad alanlarını da yeniden yüklemeniz gerekir.
Çalışan program, yeniden yüklenen ad alanındaki değerleri kapatacak işlevler içeriyorsa, bu kapalı değerler güncellenmez. (Bu, işlevlerin bir bileşimi olarak "işleyici yığını" nı oluşturan web uygulamalarında yaygındır.)
Clojure.tools.namespace kütüphanesi durumu önemli ölçüde iyileştirir. Ad alanlarının bağımlılık grafiğine dayalı olarak akıllı yeniden yükleme yapan kolay bir yenileme işlevi sağlar.
myapp.web=> (require '[clojure.tools.namespace.repl :refer [refresh]])
nil
myapp.web=> (refresh)
:reloading (myapp.web)
:ok
Maalesef, refresh
işleve başvurduğunuz ad alanı değiştiyse ikinci kez yeniden yükleme başarısız olur . Bunun nedeni, tools.namespace'in yeni kodu yüklemeden önce ad alanının geçerli sürümünü yok etmesidir.
myapp.web=> (refresh)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: refresh in this context, compiling:(/private/var/folders/ks/d6qbfg2s6l1bcg6ws_6bq4600000gn/T/form-init819543191440017519.clj:1:1)
Bu sorun için bir geçici çözüm olarak tam nitelenmiş var adını kullanabilirsiniz, ancak şahsen ben her yenileme üzerinde yazmak zorunda kalmamayı tercih ederim. Yukarıdakilerle ilgili bir başka sorun, ana ad alanını yeniden yükledikten sonra standart REPL yardımcı fonksiyonlarına ( doc
ve gibi source
) artık orada referans verilmemesidir.
Bu sorunları çözmek için, güvenilir bir şekilde yeniden yüklenebilmesi için kullanıcı ad alanı için gerçek bir kaynak dosyası oluşturmayı tercih ederim. Kaynak dosyayı koydum ~/.lein/src/user.clj
ama istediğiniz yere yerleştirebilirsiniz. Dosya, ns bildiriminde aşağıdaki gibi yenileme işlevini gerektirmelidir:
(ns user
(:require [clojure.tools.namespace.repl :refer [refresh]]))
Şunları yapabilirsiniz kurulum bir Leiningen kullanıcı profili içinde ~/.lein/profiles.clj
sınıf yoluna eklenir dosyayı koymak konum bu yüzden. Profil şöyle görünmelidir:
{:user {:dependencies [[org.clojure/tools.namespace "0.2.7"]]
:repl-options { :init-ns user }
:source-paths ["/Users/me/.lein/src"]}}
REPL başlatılırken kullanıcı ad alanını giriş noktası olarak ayarladığımı unutmayın. Bu, REPL yardımcı işlevlerine uygulamanızın ana ad alanı yerine kullanıcı ad alanında başvurulmasını sağlar. Bu şekilde yeni oluşturduğumuz kaynak dosyayı değiştirmezseniz kaybolmazlar.
Bu yardımcı olur umarım!
(use 'foo.bar :reload-all)
benim için her zaman iyi çalıştı. Ayrıca,(load-file)
sınıf yolunuzu doğru ayarladıysanız asla gerekli olmamalıdır. Alacağınız "gerekli etki" nedir?