Supposons que j'ai un tampon lisp Emacs qui contient:
(defvar foo 1)
Si j'appelle eval-last-sexp
ou eval-buffer
, foo
est lié à 1. Si j'édite alors ce tampon à:
(defvar foo 2)
eval-last-sexp
et eval-buffer
ne réexécutez pas cette ligne, il en foo
est de même pour 1.
Cela est particulièrement difficile lorsqu'il existe plusieurs déclarations de ce type et je dois déterminer quelles lignes ne sont pas réévaluées.
J'ai regardé le redémarrage d'Emacs, puis (require 'foo)
, mais je dois faire attention à ne pas charger de fichiers .elc plus anciens.
Comment puis-je être absolument, positivement sûr que les variables et les fonctions définies dans le fichier actuel sont dans le même état que le chargement de code à nouveau dans une nouvelle instance Emacs?
interactive-development
Wilfred Hughes
la source
la source
makunbound
puis réévaluer le code dans le tampon.(incf emacs-major-version)
je peux vivre avec se produire à plusieurs reprises. Je suis intéressé à pirater du code avec beaucoup dedefvar
formulaires.Réponses:
Comme expliqué dans d'autres réponses, l'évaluation d'un
defvar
formulaire à l'aide deeval-last-sexp
ne réinitialise pas la valeur par défaut.À la place, vous pouvez utiliser
eval-defun
(lié àC-M-x
inemacs-lisp-mode
par défaut), qui implémente le comportement que vous souhaitez comme exception spéciale:Si vous devez évaluer le contenu complet d'un tampon, vous pouvez écrire une fonction qui parcourt tour à tour les formulaires de niveau supérieur et appelle
eval-defun
chacun d'eux. Quelque chose comme ça devrait fonctionner:la source
eval-defun
au lieu deeval-last-sexp
. Vous pouvez même écrire une fonction qui appelleeval-defun
tous les formulaires du tampon et l'utiliser à la place deeval-buffer
.eval-defun
au lieu deeval-last-sexp
, bien sûr, mais la difficulté est poureval-buffer
.eval-defun
chaque formulaire de niveau supérieur dans le tampon.defvar
n'est pas à l'intérieur d'undefun
. Exemple:(progn (defvar foo "bar"))
.defconst
(qui sont toujours réévalués). Il y a récemment eu un article très instructif sur ce sujet entre parenthèses sans finComme le disent les autres réponses, c'est exactement ainsi que fonctionne defvar, mais vous pouvez le contourner, c'est clair après tout.
Vous pouvez redéfinir temporairement le fonctionnement de defvar si vous le souhaitez et pendant ce temps, rechargez les packages que vous souhaitez réinitialiser.
J'ai écrit une macro où lors de l'évaluation du corps, les valeurs de defvars seront toujours réévaluées.
Exemple d'utilisation:
file_a.el
file_b.el
Remarque: ceci ne doit être utilisé que dans le but de réévaluer les defvars, car il ignore simplement les docstrings lors de la réévaluation. Vous pouvez modifier la macro pour prendre en charge la réévaluation qui applique également les docstrings, mais je vous laisse le soin de le faire.
Dans votre cas, vous pourriez faire
Mais sachez ce que font ceux qui écrivent elisp en s'attendant à ce que defvar fonctionne comme spécifié, il se peut qu'ils utilisent defvar pour définir et setq dans une fonction init pour spécifier la valeur, de sorte que vous pouvez finir par des variables nulles que vous n'avez pas l'intention mais c'est probablement rare.
Mise en œuvre alternative
En utilisant cela, vous pouvez simplement redéfinir defvar globalement et contrôler s'il définira ou non la valeur du symbole sur l'argument INIT-VALUE même si le symbole est défini en modifiant la valeur du nouveau
defvar-always-reeval-values
symbole.la source
defvar
soit une bonne idée: il existe plusieurs utilisations possibles dedefvar
, avec une sémantique légèrement différente. Par exemple, une forme dont votre macro ne tient pas compte est le(defvar SYMBOL)
formulaire, qui est utilisé pour informer le compilateur d'octets de l'existence d'une variable sans définir de valeur.defvar
avec une macro, vous feriez probablement mieux de préfixer ledefvar
formulaire d' origine avec unmakunbound
, plutôt que de le remplacer parsetq
.Le
defvar
est en cours d'évaluation et fait exactement ce que vous avez spécifié. Cependant,defvar
ne définit qu'une valeur initiale:Donc, pour obtenir ce que vous voulez, vous devez soit délier la variable avant de réévaluer, par exemple
ou utilisez
setq
pour régler la valeur, par ex.Si vous n'avez pas besoin de spécifier ici une docstring, vous pouvez ignorer le
defvar
tout.Si vous voulez vraiment utiliser
defvar
et dissocier automatiquement cela, vous devrez écrire une fonction pour trouver lesdefvar
appels dans le tampon actuel (ou région, ou dernier sexp, etc.); appelermakunbound
pour chacun; puis faites l'évaluation réelle.la source
eval-buffer
wrapper qui délierait tout d'abord, mais la réponse de @ Francescoeval-defun
est vraiment ce que vous voulez.La macro suivante a été créée en traçant
eval-defun
ses fonctions de prise en charge et en la modifiant de sorte qu'il n'est plus nécessaire d'évaluer une région d'un tampon particulier. J'avais besoin d'aide dans le sujet connexe Conversion d'une expression en chaîne , et @Tobias est venu à la rescousse - m'enseignant comment convertir la fonction imparfaite en macro. Je ne pense pas que nous devionseval-sexp-add-defvars
précéderelisp--eval-defun-1
, mais si quelqu'un pense que c'est important, faites-le moi savoir.la source
Le problème n'est pas que la ligne ne soit pas réévaluée. Le problème est que
defvar
définit une variable et sa valeur par défaut . Si une variable existe déjà, la modification de sa valeur par défaut ne modifie pas la valeur actuelle. Malheureusement, je pense que vous devrez exécuter unsetq
pour chaque variable dont vous souhaitez mettre à jour la valeur.Cela peut être exagéré, mais vous pouvez mettre à jour votre fichier comme celui-ci si vous souhaitez pouvoir facilement mettre
foo
à jour sa nouvelle valeur par défaut.mais cela nécessite que vous conserviez la valeur par défaut à deux endroits dans votre code. Vous pouvez également faire ceci:
mais s'il y a une chance qui
foo
est déclarée ailleurs, vous pouvez avoir des effets secondaires à gérer.la source
eval-defun
traitedefvar
spécialement, alors il y a sûrement quelque chose de similaire pour les tampons entiers?makunbound
déclarera toutes les variables dans le tampon actuel, puis la réévaluera? Vous pouvez écrire le vôtre, mais je ne pense pas qu'il existe une fonction prête à l'emploi pour cela. EDIT: Peu importe, je comprends ce que vous dites. Uneval-defun
qui fonctionne sur tout le tampon. Il semble que @JordonBiondo ait votre solution pour cela.defvar
ne fait rien si la variable a déjà une valeur (comme le dit son doc:)The optional argument INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.
. Le problème n'est pas quedefvar
change la valeur par défaut et non la valeur actuelle.(defvar a 4) (default-value 'a) (setq a 2) (default-value 'a)
; puisC-x C-e
après ledefvar
sexp; alors(default-value 'a)
.C-x C-e
,eval-region
Et similaire sur undefvar
sexp ne pas changer la valeur par défaut.