Suponha que eu tenha um buffer lisp do Emacs que contenha:
(defvar foo 1)
Se eu ligar eval-last-sexp
ou eval-buffer
, foo
estiver vinculado a 1. Se eu editar esse buffer para:
(defvar foo 2)
eval-last-sexp
e eval-buffer
não reexecute esta linha, então foo
ainda é 1.
Isso é particularmente desafiador quando existem várias dessas declarações e eu tenho que rastrear quais linhas não estão sendo reavaliadas.
Eu olhei para reiniciar o Emacs e depois (require 'foo)
, mas tenho que ter cuidado para evitar o carregamento de arquivos .elc mais antigos.
Como posso ter certeza absoluta e positiva de que as variáveis e funções definidas no arquivo atual estão no mesmo estado que o carregamento do código novamente em uma nova instância do Emacs?
interactive-development
Wilfred Hughes
fonte
fonte
makunbound
e reavaliar o código no buffer.(incf emacs-major-version)
eu posso viver acontecendo repetidamente. Estou interessado em invadir o código com muitosdefvar
formulários.Respostas:
Conforme explicado em outras respostas, a avaliação de um
defvar
formulário usandoeval-last-sexp
não redefine o valor padrão.Em vez disso, você pode usar
eval-defun
(vinculado aC-M-x
inemacs-lisp-mode
por padrão), que implementa o comportamento desejado como uma exceção especial:Se você precisar avaliar o conteúdo completo de um buffer, poderá escrever uma função que percorra os formulários de nível superior por vez e chame
eval-defun
cada um. Algo assim deve funcionar:fonte
eval-defun
vez deeval-last-sexp
. Você pode até escrever uma função que chamaeval-defun
todos os formulários do buffer e usá-la em vez deeval-buffer
.eval-defun
vez deeval-last-sexp
, com certeza, mas a dificuldade é paraeval-buffer
.eval-defun
todos os formulários de nível superior no buffer.defvar
não estiver dentro de adefun
. Exemplo:(progn (defvar foo "bar"))
.defconst
(que são sempre reavaliados). Houve recentemente um post muito esclarecedor sobre este tema em parênteses intermináveisComo as outras respostas dizem, é assim que o defvar funciona, mas você pode contornar isso, afinal é o elisp.
Você pode redefinir temporariamente como o defvar funciona, se desejar, e durante esse período, recarregar os pacotes que deseja redefinir.
Escrevi uma macro em que, durante a avaliação do corpo, os valores defvars serão sempre reavaliados.
Exemplo de uso:
file_a.el
file_b.el
Nota: Isso deve ser usado apenas com a finalidade de reavaliar defvars, pois apenas ignora as doutrinas ao reavaliar. Você pode modificar a macro para dar suporte à reavaliação que também aplica doutrinas, mas deixarei isso para você.
No seu caso, você poderia fazer
Mas saiba o que aqueles que escrevem elisp esperam que o defvar funcione conforme especificado, pode ser que eles usem o defvar para definir e setq em alguma função init para especificar o valor, para que você possa acabar sem variáveis que não pretende, mas isso é provavelmente raro.
Implementação Alternativa
Usando isso, você pode redefinir o defvar globalmente e controlar se ele definirá ou não o valor do símbolo para o argumento INIT-VALUE, mesmo que o símbolo seja definido alterando o valor do novo
defvar-always-reeval-values
símbolo.fonte
defvar
é uma boa idéia: existem vários usos possíveis dedefvar
, com semântica ligeiramente diferente. Por exemplo, um uso que sua macro não considera é o(defvar SYMBOL)
formulário, que é usado para informar o compilador de bytes sobre a existência de uma variável sem definir um valor.defvar
com uma macro, provavelmente seria melhor prefixar odefvar
formulário original com amakunbound
, em vez de substituí-losetq
.O
defvar
está sendo avaliado e fazendo exatamente o que você especificou. No entanto,defvar
define apenas um valor inicial:Portanto, para alcançar o que você deseja, você precisará desvincular a variável antes de reavaliar, por exemplo
ou use
setq
para definir o valor, por exemploSe você não precisar especificar uma sequência de documentos aqui, poderá pular
defvar
completamente.Se você realmente deseja usar
defvar
e desvincular automaticamente isso, precisará escrever uma função para encontrardefvar
chamadas no buffer atual (ou região, ou último sexp, etc); liguemakunbound
para cada um; e então faça a avaliação real.fonte
eval-buffer
invólucro que desvendaria tudo primeiro, mas a resposta de @ Francescoeval-defun
é realmente o que você deseja.A macro a seguir foi criada rastreando
eval-defun
suas funções de suporte e modificando-a para que não seja mais necessário avaliar uma região de um buffer específico. Eu precisava de ajuda no thread relacionado Convertendo uma expressão em uma string , e o @Tobias veio em socorro - me ensinando como converter a função imperfeita em uma macro. Não acho que precisamoseval-sexp-add-defvars
precederelisp--eval-defun-1
, mas se alguém achar importante, informe-me.fonte
O problema não é que a linha não esteja sendo reavaliada. O problema é que
defvar
define uma variável e seu valor padrão . Se uma variável já existir, a alteração do valor padrão não modifica o valor atual. Infelizmente, acho que você precisará executar umsetq
para cada variável cujo valor você deseja atualizar.Isso pode ser um exagero, mas você pode atualizar seu arquivo assim se quiser atualizar facilmente
foo
para seu novo valor padrão.mas isso exige que você mantenha o valor padrão em dois lugares no seu código. Você também pode fazer isso:
mas se houver uma chance
foo
declarada em outro lugar, você poderá ter alguns efeitos colaterais.fonte
eval-defun
tratadefvar
especialmente, então certamente há algo semelhante para buffers inteiros?makunbound
declare todas as variáveis no buffer atual e depois a reavalie? Você poderia escrever o seu próprio, mas não acho que exista uma função pronta para isso. EDIT: Não importa, eu entendo o que você está dizendo. Umeval-defun
que funciona em todo o buffer. Parece que @JordonBiondo tem sua solução para isso.defvar
não faz nada se a variável já tiver um valor (como diz o documento:)The optional argument INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.
. O problema não é quedefvar
altera o valor padrão e não o valor atual.(defvar a 4) (default-value 'a) (setq a 2) (default-value 'a)
; em seguida,C-x C-e
após odefvar
sexp; então(default-value 'a)
.C-x C-e
,eval-region
E afins em umdefvar
sexp que não alterar o valor padrão.