Supongamos que tengo un búfer Emacs lisp que contiene:
(defvar foo 1)
Si llamo eval-last-sexp
o eval-buffer
, foo
está vinculado a 1. Si luego edito este búfer para:
(defvar foo 2)
eval-last-sexp
y eval-buffer
no vuelva a ejecutar esta línea, por foo
lo que sigue siendo 1.
Esto es particularmente desafiante cuando hay múltiples declaraciones de este tipo y tengo que rastrear qué líneas no se están reevaluando.
Miré simplemente reiniciar Emacs y luego (require 'foo)
, pero luego tengo que tener cuidado para evitar cargar cualquier archivo .elc anterior.
¿Cómo puedo estar absolutamente seguro de que las variables y funciones definidas en el archivo actual están en el mismo estado que el código de carga nuevamente en una nueva instancia de Emacs?
interactive-development
Wilfred Hughes
fuente
fuente
makunbound
y luego volver a evaluar el código en el búfer.(incf emacs-major-version)
que puedo vivir ocurren repetidamente. Estoy interesado en hackear el código con muchasdefvar
formas.Respuestas:
Como se explica en otras respuestas, la evaluación de un
defvar
formulario usandoeval-last-sexp
no restablece el valor predeterminado.En su lugar, puede utilizar
eval-defun
(con destinoC-M-x
enemacs-lisp-mode
forma predeterminada), que implementa el comportamiento que desea como una excepción especial:Si necesita evaluar el contenido completo de un búfer, puede escribir una función que recorra los formularios de nivel superior y llame
eval-defun
a cada uno. Algo como esto debería funcionar:fuente
eval-defun
lugar deeval-last-sexp
. Incluso puede escribir una función que llameeval-defun
a cada formulario en el búfer y usarlo en lugar deeval-buffer
.eval-defun
lugar deeval-last-sexp
, claro, pero la dificultad es paraeval-buffer
.eval-defun
a cada formulario de nivel superior en el búfer.defvar
no está dentro de adefun
. Ejemplo:(progn (defvar foo "bar"))
.defconst
(que siempre se reevalúan). Recientemente ha habido una publicación muy esclarecedora sobre este tema entre paréntesis interminablesComo dicen las otras respuestas, esta es la forma en que defvar funciona, pero puedes evitarlo, después de todo, es elisp.
Puede redefinir temporalmente cómo funciona defvar si lo desea y, durante ese tiempo, volver a cargar los paquetes que desea restablecer.
Escribí una macro donde durante la evaluación del cuerpo, los valores de defvars siempre serán reevaluados.
Ejemplo de uso:
file_a.el
file_b.el
Nota: Esto solo debe usarse con el propósito de reevaluar los defvars, ya que simplemente ignora las cadenas de documentos al reevaluar. Puede modificar la macro para admitir la reevaluación que también aplica docstrings, pero se lo dejaré a usted.
En tu caso podrías hacer
Pero sepa lo que hacen los que escriben elisp esperando que defvar funcione como se especifica, podría ser que usan defvar para definir y establecer q en alguna función de inicio para especificar el valor, por lo que puede terminar con variables nulas que no pretende pero Esto es probablemente raro.
Implementación Alternativa
Con esto, puede redefinir defvar globalmente y controlar si establecerá o no el valor del símbolo en el argumento INIT-VALUE incluso si el símbolo se define cambiando el valor del nuevo
defvar-always-reeval-values
símbolo.fuente
defvar
es una buena idea: hay varios usos posibles diferentesdefvar
, con semánticas ligeramente diferentes. Por ejemplo, un uso que su macro no tiene en cuenta es el(defvar SYMBOL)
formulario, que se utiliza para decirle al compilador de bytes sobre la existencia de una variable sin establecer un valor.defvar
con una macro, probablemente sea mejor prefijar eldefvar
formulario original con amakunbound
, en lugar de reemplazarlo porsetq
.Se
defvar
está evaluando y haciendo exactamente lo que ha especificado. Sin embargo,defvar
solo establece un valor inicial:Entonces, para lograr lo que desea, necesitaría desvincular la variable antes de reevaluar, por ejemplo
o use
setq
para establecer el valor, por ej.Si no necesita especificar una cadena de documentación aquí, puede omitirla por
defvar
completo.Si realmente desea usar
defvar
y desvincular esto automáticamente, deberá escribir una función para buscardefvar
llamadas en el búfer actual (o región, o el último sexp, etc.); llamamakunbound
a cada uno; y luego hacer la evaluación real.fuente
eval-buffer
envoltura que desenredaría todo primero, pero la respuesta de @ Francescoeval-defun
es realmente lo que quieres.La siguiente macro se creó rastreando
eval-defun
sus funciones de soporte y modificándola para que ya no sea necesario evaluar una región de un búfer particular. Necesitaba ayuda en el hilo relacionado Convirtiendo una expresión en una cadena , y @Tobias acudió al rescate, enseñándome cómo convertir la función imperfecta en una macro. No creo que tengamoseval-sexp-add-defvars
que precederelisp--eval-defun-1
, pero si alguien piensa que es importante, hágamelo saber.fuente
El problema no es que la línea no se vuelva a evaluar. El problema es que
defvar
define una variable y su valor predeterminado . Si ya existe una variable, cambiar su valor predeterminado no modifica el valor actual. Desafortunadamente, creo que necesitará ejecutar unsetq
para cada variable cuyo valor desea actualizar.Esto puede ser excesivo, pero puede actualizar su archivo de esta manera si desea poder actualizar fácilmente
foo
a su nuevo valor predeterminado.pero eso requiere que mantenga el valor predeterminado en dos lugares en su código. También puedes hacer esto:
pero si existe la posibilidad de que
foo
se declare en otro lugar, puede tener algunos efectos secundarios para tratar.fuente
eval-defun
tratadefvar
especialmente, así que seguramente hay algo similar para tampones enteros?makunbound
las variables declaradas en el búfer actual y luego la reevalúe? Podrías escribir el tuyo, pero no creo que haya una función lista para usar para esto. EDITAR: No importa, entiendo lo que estás diciendo. Uneval-defun
que funciona en todo el búfer. Parece que @JordonBiondo tiene su solución para eso.defvar
no hace nada si la variable ya tiene un valor (como dice su documento:)The optional argument INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.
. El problema no es quedefvar
cambie el valor predeterminado y no el valor actual.(defvar a 4) (default-value 'a) (setq a 2) (default-value 'a)
; luegoC-x C-e
después deldefvar
sexp; entonces(default-value 'a)
.C-x C-e
,eval-region
y similares en undefvar
sexp no cambian el valor predeterminado.