Załóżmy, że mam bufor Lisp Emacsa, który zawiera:
(defvar foo 1)
Jeśli zadzwonię eval-last-sexp
lub eval-buffer
, foo
zostanie przypisane do 1. Jeśli następnie zmodyfikuję ten bufor do:
(defvar foo 2)
eval-last-sexp
i eval-buffer
nie wykonuj ponownie tej linii, więc foo
nadal jest 1.
Jest to szczególnie trudne, gdy istnieje wiele takich stwierdzeń i muszę wyśledzić, które wiersze nie podlegają ponownej ocenie.
(require 'foo)
Patrzyłem na ponowne uruchomienie Emacsa , ale potem musiałem uważać, aby nie załadować żadnych starszych plików .elc.
Jak mogę mieć absolutną, pozytywną pewność, że zmienne i funkcje zdefiniowane w bieżącym pliku są w tym samym stanie, co ładowanie kodu na nowo w nowej instancji Emacsa?
interactive-development
Wilfred Hughes
źródło
źródło
makunbound
a następnie ponownie ocenić kod w buforze.(incf emacs-major-version)
Mogę żyć z powtarzaniem się. Interesuje mnie hackowanie kodu za pomocą wieludefvar
formularzy.Odpowiedzi:
Jak wyjaśniono w innych odpowiedziach, ocena
defvar
formularza za pomocąeval-last-sexp
nie resetuje wartości domyślnej.Zamiast tego można użyć
eval-defun
(związanyC-M-x
wemacs-lisp-mode
domyślnie), który implementuje zachowanie chcesz jako wyjątek specjalny:Jeśli musisz ocenić pełną zawartość bufora, możesz napisać funkcję, która przechodzi kolejno do formularzy najwyższego poziomu i wywołuje
eval-defun
każdą z nich. Coś takiego powinno działać:źródło
eval-defun
zamiasteval-last-sexp
. Możesz nawet napisać funkcję, która wywołujeeval-defun
każdą formę w buforze i używać jej zamiasteval-buffer
.eval-defun
zamiasteval-last-sexp
, oczywiście, ale trudność jest dlaeval-buffer
.eval-defun
każdą formę najwyższego poziomu w buforze.defvar
nie ma go wdefun
. Przykład:(progn (defvar foo "bar"))
.defconst
(które są zawsze ponownie oceniane). Niedawno pojawił się bardzo pouczający post na ten temat w niekończących się nawiasachTak jak inne odpowiedzi mówią, tak działa defvar, ale można to obejść, w końcu jest elisp.
Możesz tymczasowo zmienić sposób działania defvar, jeśli chcesz, i w tym czasie ponownie załaduj pakiety, które chcesz zresetować.
Napisałem makro, w którym podczas oceny ciała wartości defvars zawsze będą przewartościowane.
Przykładowe użycie:
plik_a.el
plik_b.el
Uwaga: należy tego używać wyłącznie w celu ponownej oceny defvarów, ponieważ po prostu ignoruje ona dokumenty podczas ponownej oceny. Możesz zmodyfikować makro w celu obsługi ponownej oceny, która dotyczy również dokumentów, ale pozostawię to tobie.
W twoim przypadku możesz to zrobić
Ale wiedz, co robią ci, którzy piszą elisp, oczekując, że defvar będzie działał zgodnie ze specyfikacją, może być tak, że używają defvar do definiowania i setq w jakiejś funkcji init, aby określić wartość, więc możesz skończyć na zerowych zmiennych, których nie zamierzasz, ale jest to prawdopodobnie rzadkie.
Alternatywne wdrożenie
Za pomocą tego możesz po prostu przedefiniować globalnie defvar i kontrolować, czy ustawi wartość symbolu na wartość INIT-VALUE arg, nawet jeśli symbol jest zdefiniowany przez zmianę wartości nowego
defvar-always-reeval-values
symbolu.źródło
defvar
jest dobrym pomysłem: istnieje kilka różnych możliwych zastosowańdefvar
, z nieco inną semantyką. Na przykład jednym z zastosowań, których nie uwzględnia twoje makro, jest(defvar SYMBOL)
formularz, który służy do informowania kompilatora bajtów o istnieniu zmiennej bez ustawiania wartości.defvar
za pomocą makra, prawdopodobnie lepiej byłoby przedrostkować oryginalnydefvar
formularzmakunbound
zamiast, zamiast go zastąpićsetq
.defvar
Jest oceniany i robi dokładnie to, co już określona. Jednakdefvar
ustawia tylko wartość początkową:Aby więc osiągnąć to, co chcesz, musisz albo odłączyć zmienną przed ponowną oceną, np
lub użyj,
setq
aby ustawić wartość, npJeśli nie musisz tutaj określać dokumentu, możesz go
defvar
całkowicie pominąć .Jeśli naprawdę chcesz tego użyć
defvar
i automatycznie cofnąć powiązanie, musisz napisać funkcję, aby znaleźćdefvar
wywołania w bieżącym buforze (lub regionie, lub ostatnim sexp itp.); wezwaćmakunbound
każdego; a następnie wykonaj rzeczywistą ewaluację.źródło
eval-buffer
Bawiłem się opakowaniem, które najpierw rozwiąże wszystko, ale odpowiedź @ Francescoeval-defun
jest naprawdę tym, czego chcesz.Poniższe makro zostało utworzone poprzez śledzenie
eval-defun
jego funkcji pomocniczych i modyfikowanie go, aby nie było już konieczne ocenianie regionu określonego bufora. Potrzebowałem pomocy w powiązanym wątku Konwertowanie wyrażenia na ciąg znaków , a @Tobias przybyło na ratunek - ucząc mnie, jak przekształcić niedoskonałą funkcję w makro. Nie sądzę, że musimyeval-sexp-add-defvars
poprzedzaćelisp--eval-defun-1
, ale jeśli ktoś uważa, że to ważne, daj mi znać.źródło
Problemem nie jest to, że linia nie podlega ponownej ocenie. Problem polega na tym, że
defvar
definiuje zmienną i jej wartość domyślną . Jeśli zmienna już istnieje, zmiana jej wartości domyślnej nie modyfikuje bieżącej wartości. Niestety myślę, że będziesz musiał uruchomićsetq
dla każdej zmiennej, której wartość chcesz zaktualizować.Może to być przesada, ale możesz zaktualizować plik w ten sposób, jeśli chcesz mieć możliwość łatwej aktualizacji
foo
do nowej wartości domyślnej.ale wymaga to zachowania domyślnej wartości w dwóch miejscach w kodzie. Możesz także to zrobić:
ale jeśli istnieje szansa
foo
zadeklarowana gdzie indziej, możesz mieć pewne skutki uboczne do pokonania.źródło
eval-defun
traktujedefvar
specjalnie, więc na pewno jest coś podobnego dla całych buforów?makunbound
dowolnymi zmiennymi zadeklarowanymi w bieżącym buforze, a następnie ponownie ją oceni? Możesz napisać własny, ale nie sądzę, że jest do tego gotowa funkcja. EDYCJA: Nieważne, rozumiem co mówisz.eval-defun
Który działa na cały bufor. Wygląda na to, że @JordonBiondo ma na to odpowiednie rozwiązanie.defvar
nic nie robi, jeśli zmienna ma już wartość (jak mówi jej dokument:)The optional argument INITVALUE is evaluated, and used to set SYMBOL, only if SYMBOL's value is void.
. Problemem nie jest to, żedefvar
zmienia wartość domyślną, a nie bieżącą.(defvar a 4) (default-value 'a) (setq a 2) (default-value 'a)
; potemC-x C-e
podefvar
sexp; potem(default-value 'a)
.C-x C-e
,eval-region
i tym podobne wdefvar
sexp nie zmieniają wartości domyślnej.