Quelle est la manière préférée de recharger les fonctions définies dans un fichier Clojure sans avoir à redémarrer le REPL. Pour le moment, pour utiliser le fichier mis à jour, je dois:
- Éditer
src/foo/bar.clj
- fermer le REPL
- ouvrir le REPL
(load-file "src/foo/bar.clj")
(use 'foo.bar)
De plus, (use 'foo.bar :reload-all)
n'entraîne pas l'effet requis, qui évalue les corps modifiés des fonctions et renvoie de nouvelles valeurs, au lieu de se comporter comme la source n'a pas du tout changé.
Documentation:
(use 'foo.bar :reload-all)
a toujours bien fonctionné pour moi. De plus, cela(load-file)
ne devrait jamais être nécessaire si votre chemin de classe est correctement configuré. Quel est l '«effet requis» que vous n'obtenez pas?bar.clj
détaillant "l'effet requis".(defn f [] 1)
et que je changeais sa définition en(defn f [] 2)
, il me semblait qu'après avoir émis(use 'foo.bar :reload-all)
et appelé laf
fonction, elle devrait renvoyer 2, pas 1. Malheureusement, cela ne fonctionne pas de cette façon pour moi et chaque fois que je change le corps de la fonction, je dois redémarrer le REPL.:reload
ou les:reload-all
deux devraient fonctionner.Réponses:
Ou
(use 'your.namespace :reload)
la source
:reload-all
devrait également fonctionner. L'OP dit spécifiquement que non, mais je pense qu'il y avait autre chose qui n'allait pas dans l'environnement de développement de l'OP parce que pour un seul fichier, les deux (:reload
et:reload-all
) devraient avoir le même effet. Voici la commande complète pour:reload-all
:(use 'your.namespace :reload-all)
Cela recharge également toutes les dépendances.Il existe également une alternative comme utiliser tools.namespace , c'est assez efficace:
la source
(refresh)
semble également faire oublier à la REPL que vous en avez besoinclojure.tools.namespace.repl
. Les appels suivants à(refresh)
vous donneront une exception RuntimeException, "Impossible de résoudre le symbole: actualiser dans ce contexte." Probablement la meilleure chose à faire est soit(require 'your.namespace :reload-all)
, ou, si vous savez que vous allez vouloir rafraîchir REPL beaucoup pour un projet donné, faire un:dev
profil et ajouter[clojure.tools.namespace.repl :refer (refresh refresh-all)]
àdev/user.clj
.Le rechargement du code Clojure en utilisant
(require … :reload)
et:reload-all
est très problématique :La bibliothèque clojure.tools.namespace améliore considérablement la situation. Il fournit une fonction d'actualisation facile qui effectue un rechargement intelligent basé sur un graphique de dépendance des espaces de noms.
Malheureusement, un deuxième rechargement échouera si l'espace de noms dans lequel vous avez référencé la
refresh
fonction a changé. Cela est dû au fait que tools.namespace détruit la version actuelle de l'espace de noms avant de charger le nouveau code.Vous pouvez utiliser le nom var complet comme solution de contournement à ce problème, mais personnellement, je préfère ne pas avoir à le taper à chaque actualisation. Un autre problème avec ce qui précède est qu'après le rechargement de l'espace de noms principal, les fonctions d'assistance REPL standard (comme
doc
etsource
) n'y sont plus référencées.Pour résoudre ces problèmes, je préfère créer un fichier source réel pour l'espace de noms utilisateur afin qu'il puisse être rechargé de manière fiable. J'ai mis le fichier source
~/.lein/src/user.clj
mais vous pouvez le placer n'importe où. Le fichier doit nécessiter la fonction de rafraîchissement dans la déclaration ns supérieure comme ceci:Vous pouvez configurer un profil utilisateur leiningen
~/.lein/profiles.clj
pour que l'emplacement dans lequel vous placez le fichier soit ajouté au chemin de classe. Le profil doit ressembler à ceci:Notez que j'ai défini l'espace de noms utilisateur comme point d'entrée lors du lancement du REPL. Cela garantit que les fonctions d'assistance REPL sont référencées dans l'espace de noms utilisateur au lieu de l'espace de noms principal de votre application. De cette façon, ils ne se perdront que si vous modifiez le fichier source que nous venons de créer.
J'espère que cela t'aides!
la source
:source-paths
je reçois#<FileNotFoundException java.io.FileNotFoundException: Could not locate user__init.class or user.clj on classpath: >
, alors qu'avec:resource-paths
tout va bien.:resource-paths
, je suis dans mon espace de noms d'utilisateur à l'intérieur de repl.reload
problème. Ensuite, il s'est avéré que tout ce que je pensais fonctionner ne fonctionnait plus. Peut-être que quelqu'un devrait régler cette situation?La meilleure réponse est:
Cela rechargera non seulement votre espace de noms spécifié, mais rechargera également tous les espaces de noms de dépendances.
Documentation:
exiger
la source
lein repl
, Coljure 1.7.0 et nREPL 0.3.5. Si vous êtes nouveau dans clojure: L'espace de noms ('my.namespace
) est défini avec(ns ...)
insrc/
.../core.clj
, par exemple.proj.stuff.core
reflète la structure des fichiers sur le disquesrc/proj/stuff/core.clj
, le REPL peut localiser le fichier correct et vous n'en avez pas besoinload-file
.Une doublure basée sur la réponse de Papachan:
la source
J'utilise ceci dans Lighttable (et l'impressionnant instarepl) mais cela devrait être utile dans d'autres outils de développement. J'avais le même problème avec les anciennes définitions de fonctions et de méthodes multiples qui traînaient après les recharges, alors maintenant pendant le développement au lieu de déclarer des espaces de noms avec:
Je déclare mes espaces de noms comme ceci:
Assez moche mais chaque fois que je réévalue tout l'espace de noms (Cmd-Shift-Enter dans Lighttable pour obtenir les nouveaux résultats instarepl de chaque expression), cela supprime toutes les anciennes définitions et me donne un environnement propre. J'ai été trébuché tous les quelques jours par d'anciennes définitions avant de commencer à faire cela et cela m'a sauvé la raison. :)
la source
Essayez à nouveau de charger le fichier?
Si vous utilisez un IDE, il existe généralement un raccourci clavier pour envoyer un bloc de code au REPL, redéfinissant ainsi efficacement les fonctions associées.
la source
Dès que cela
(use 'foo.bar)
fonctionne pour vous, cela signifie que vous avez foo / bar.clj ou foo / bar_init.class sur votre CLASSPATH. Le bar_init.class serait une version compilée AOT de bar.clj. Si vous le faites(use 'foo.bar)
, je ne sais pas exactement si Clojure préfère la classe à clj ou l'inverse. S'il préfère les fichiers de classe et que vous avez les deux fichiers, il est clair que la modification du fichier clj puis le rechargement de l'espace de noms n'ont aucun effet.BTW: Vous n'avez pas besoin de le faire
load-file
avant leuse
si votre CLASSPATH est correctement réglé.BTW2: Si vous avez besoin d'utiliser
load-file
pour une raison, vous pouvez simplement le refaire si vous avez modifié le fichier.la source