Comment recharger une clojure fichier dans REPL
Quel est le meilleur moyen de recharger les fonctions définies dans un Clojure fichier sans avoir à redémarrer le REPL. Dès maintenant, afin d'utiliser le fichier mis à jour j'ai:
- modifier
src/foo/bar.clj
- fermer le REPL
- ouvrir le REPL
(load-file "src/foo/bar.clj")
(use 'foo.bar)
En outre, (use 'foo.bar :reload-all)
ne résulte pas en effet requis, qui est de l'évaluation de la modification des corps de fonctions et de retour, de nouvelles valeurs, au lieu de se comporter en tant que la source n'ont pas changé.
(use 'foo.bar :reload-all)
a toujours fonctionné pour moi. Aussi,(load-file)
ne devrait jamais être nécessaire si vous avez votre classpath mis en place. Qu'est-ce que "l'effet" vous n'obtenez pas?- Oui, qu'est-ce que le "effet"? Poster un échantillon
bar.clj
de détails sur le "effet". - En effet je voulais dire que si j'avais une fonction
(defn f [] 1)
et j'ai changé sa définition de(defn f [] 2)
, il me semblait que lorsque j'question(use 'foo.bar :reload-all)
et d'appeler laf
la fonction doit retourner 2, pas 1. Malheureusement, il ne fonctionne pas comme cela pour moi et chaque fois que je change le corps de la fonction, j'ai redémarrer le REPL. - Vous devez avoir un autre problème dans votre configuration...
:reload
ou:reload-all
devrait à la fois de travail.
Vous devez vous connecter pour publier un commentaire.
Ou
(use 'your.namespace :reload)
:reload-all
devrait également fonctionner. L'OP spécifiquement dit qu'il ne l'est pas, mais je pense qu'il y avait autre chose de mal dans le cas des OP environnement de dev parce que pour un seul fichier les deux (:reload
et:reload-all
) devrait avoir le même effet. Voici l'intégralité de la commande pour:reload-all
:(use 'your.namespace :reload-all)
Cette recharge toutes les dépendances, trop.Il ya aussi une alternative comme l'utilisation de outils.espace de noms, c'est assez efficace:
(refresh)
semble également provoquer le REPL à oublier que vous avez requisclojure.tools.namespace.repl
. Les appels suivants à(refresh)
vous donnera une RuntimeException, "Impossible de résoudre symbole: l'actualisation dans ce contexte." Probablement la meilleure chose à faire est soit de(require 'your.namespace :reload-all)
, ou, si vous savez que vous allez avoir à actualiser votre REPL beaucoup pour un projet donné, faire un:dev
profil et ajouter[clojure.tools.namespace.repl :refer (refresh refresh-all)]
àdev/user.clj
.Rechargement Clojure code à l'aide de
(require … :reload)
et:reload-all
est très problématique:La clojure.outils.espace de noms de la bibliothèque améliore de manière significative la situation. Il fournit une simple actualisation de la fonction intelligente de rechargement basé sur un graphe de dépendance des espaces de noms.
Malheureusement recharger un deuxième temps échouera si l'espace de noms dans lequel vous avez référencé le
refresh
fonction changé. Cela est dû au fait que les outils.espace de noms détruit la version actuelle de l'espace de noms avant de charger le nouveau code.Vous pouvez utiliser le complet le var nom comme une solution de contournement pour ce problème, mais personnellement je préfère ne pas avoir à taper que sur chaque actualisation. Un autre problème avec le ci-dessus est que, après le rechargement de l'espace principal de la norme REPL des fonctions d'assistance (comme
doc
etsource
) ne sont plus référencés là.Pour résoudre ces questions, je préfère créer un fichier source pour l'utilisateur de l'espace de noms, de sorte qu'il peut être facilement rechargé. J'ai mis le fichier source dans
~/.lein/src/user.clj
mais vous pouvez le placer n'importe où. Le fichier devrait exiger de la fonction de rafraîchissement dans le top ns déclaration comme ceci:Vous pouvez configurer un leiningen profil de l'utilisateur dans
~/.lein/profiles.clj
de sorte que l'emplacement que vous avez mis le fichier est ajouté au chemin de classe. Le profil devrait ressembler à quelque chose comme ceci:Noter que j'ai mis le nom d'utilisateur de l'espace de noms comme le point d'entrée lors du lancement de la REPL. Cela garantit que le REPL fonctions d'aide pour obtenir référencé dans le manuel d'espace de noms au lieu de l'espace principal de votre application. De cette façon, ils ne seront pas perdus, sauf si vous modifiez le fichier source que nous venons de créer.
Espérons que cette aide!
:resource-paths
🙂:source-paths
- je obtenir#<FileNotFoundException java.io.FileNotFoundException: Could not locate user__init.class or user.clj on classpath: >
, tandis qu'avec:resource-paths
tout est ok.~/.lein/user/user.clj
avec d'autres trucs:resource-paths
, je suis dans mon utilisateur de l'espace de noms à l'intérieur de repl.La meilleure réponse est:
Cela permettra non seulement de recharger votre espace de noms spécifié, mais permettra de recharger tous dépendance espaces de bien.
lein repl
, Coljure 1.7.0 et nREPL 0.3.5. Si vous êtes nouveau à clojure: L'espace de noms ('my.namespace
) est définie avec(ns ...)
danssrc/
.../core.clj
, par exemple.proj.stuff.core
miroirs de la structure des fichiers sur le disque commesrc/proj/stuff/core.clj
, le REPL pouvez localiser le bon fichier et que vous n'avez pas besoinload-file
.Un liner basé sur papachan réponse:
- Je l'utiliser dans Lighttable (et le génial instarepl), mais il convient de les utiliser dans d'autres outils de développement. J'ai eu le même problème avec les anciennes définitions de fonctions et de multimethods traîner après recharge donc maintenant en cours de développement au lieu de déclarer les espaces de noms avec:
Je déclarer mes espaces de noms comme ceci:
Assez laid, mais à chaque fois que je re-évaluer la totalité de l'espace de noms (Cmd-Maj-Entrée en Lighttable pour obtenir le nouveau instarepl résultats de chaque expression), elle s'envole toutes les anciennes définitions et me donne un environnement propre. J'ai été fauché tous les quelques jours par les anciennes définitions avant j'ai commencé à faire cela et il a sauvé ma santé mentale. 🙂
Essayez de charge-fichier de nouveau?
Si vous utilisez un IDE, il y a généralement un raccourci clavier pour envoyer un code-block à la REPL, donc re-définir les fonctions associées.
Dès que
(use 'foo.bar)
qui fonctionne pour vous, cela signifie que vous avez foo/bar.clj ou foo/bar_init.class sur votre chemin de classe. L'bar_init.class serait une AOT-version compilée de la barre.clj. Si vous ne(use 'foo.bar)
, je ne suis pas sûr si Clojure préfère classe, plus clj ou l'inverse. Si elle préfère les fichiers de classe et que vous avez deux fichiers, alors il est clair que la modification du clj fichier, puis le rechargement de l'espace de noms n'a pas d'effet.BTW: Vous n'avez pas besoin de
load-file
avant lause
si votre classe est définie correctement.BTW2: Si vous avez besoin d'utiliser
load-file
pour une raison, alors vous pouvez simplement le faire à nouveau si vous avez édité le fichier.