Nie jestem całkiem pewien na temat wszystkich odmian zmiennych lokalnych buforów, nawet po przeczytaniu wszystkich dokumentów i kilku postów tutaj na SX.
Oto podsumowanie mojego zrozumienia:
(defvar foo ..)
deklaruje zmienną dynamiczną dla pliku. Ale zmienna (1) nie jest znana innym plikom, chyba że zawierają one również defvar
instrukcję, oraz (2) zmienna ma zasięg globalny, a nie bufor lokalny.
(make-variable-buffer-local foo)
po defvar
powyższym informuje kompilator i wszystkich innych, że zmienna foo ma być traktowana jako bufor lokalna wszędzie tam, gdzie jest ustawiona, kiedy jest ustawiona. Ten wzorzec jest dobrym stylem do deklarowania zmiennej lokalnej bufora, umieszczając obie instrukcje w pliku z powrotem.
(defvar xxx ...) ;declare xxx with global scope
(make-variable-buffer-local 'xxx) ;but now make it buffer-local everywhere
Dla wygody (defvar-local xxx ...)
formularz można wykorzystać jako jedną linię zamiast dwóch linii powyżej:
(defvar-local xxx ...) ;make xxx buffer local everywhere
Po zadeklarowaniu jak powyżej zmienna xxx może być używana jak każda inna zmienna w instrukcjach setq.
Jeśli chcę mieć tylko jedną instancję zmiennej lokalnej bufora, która jest już globalną zmienną dynamiczną, użyłbym następujących deklaracji. Pierwsza deklaruje zmienną dynamiczną o zasięgu globalnym, a druga instrukcja tworzy tylko jedną instancję lokalnej wersji tej zmiennej w buforze:
(defvar xxx ...) ;declare xxx with global scope
(make-local-variable 'xxx) ;make xxx local in this buffer only
Teraz moje pytania wyjaśniające (wszystkie powyższe były dorozumianymi pytaniami, czy moje rozumienie jest prawidłowe).
Podczas ustawiania wartości zmiennych mogę użyć setq
lub
setq-local
. Kiedy należy setq-local
stosować? Dlaczego?
Co się stanie, jeśli korzystam setq-local
z lokalnych zmiennych buforujących lub zmiennych lokalnych buforujących?
Czy setq-local
wymagana jest defvar-local
deklarowana zmienna?
Czy setq-local
normalna defvar
deklarowana zmienna zmieni ją w zmienną lokalną w buforze? (Innymi słowy, czy w setq-local
jakiś sposób jest to odpowiednik (make-variable-local xxx)
deklaracji?
źródło
(setq-local VAR VALUE)
jest po prostu skrótem(set (make-local-variable VAR) VALUE)
, który był (i nadal jest) powszechnym idiomem.Odpowiedzi:
Większość twoich założeń jest bliska. Wspomnę kilka później. Ale najpierw najważniejsze pytanie.
Forma
setq-local
jest jedynie wygodą, jest taka sama jak robienie,make-local-variable
po której następujesetq
. Jeśli zrobiłeś a, C-h f setq-localaby zobaczyć dokumentację i przeszedłeś do źródła, mógłbyś to zobaczyć. W ten sposób zweryfikowałem moje pierwsze wrażenie. Kod jest jednak nieco niejasny, ponieważ optymalizuje takie rzeczy, jak fakt, żemake-local-variable
faktycznie zwraca samą zmienną. Użyciesetq-local
jest sposobem na wskazanie lokalności w pewnym kodzie, aby inni wiedzieli, że kod nie może grać z globalną wartością zmiennej. Zdajesz nie trzeba go używać, aby uzyskać dostęp zmienne lokalne. Każda zmienna może być lokalna w buforze, co wpłynie na cały kod, który dotyka zmiennej (z wyjątkiem sytuacji, gdy nie będzie w stanie uzyskać kopii globalnej za pomocąsetq-default
lub podobnej).To jest podstawowa odpowiedź. Teraz w twoim tle jest kilka rzeczy, które są trochę nie w porządku. Skoro o to pytałeś, zajmę się niektórymi rzeczami.
Pierwszy jest „nieznany innym plikom”. To nie jest do końca prawda. Każdy kod może odwoływać się do dowolnej zmiennej globalnej (dlatego nazywane są „globalnymi”) bez uwzględnienia
defvar
(i C-h f defvartak mówi). W rzeczywistości powinna istnieć tylko jedna głównadefvar
(z dokumentacją i wartością domyślną) dla każdej zmiennej globalnej. Adefvar
z samą nazwą zmiennej można pominąć ostrzeżenie kompilatora bajtów. Emacs używa tylko wartości z pierwszej, którą widzi¹, oraz docstring z ostatniej. Jeśli jest wieledefvar
znaków z wartością / docstring, mogą być mylące dla osób czytających kod. Kolejność ładowania plików będzie miała znaczenie.Niektóre zmienne są przeznaczone do stosowania tylko bufor lokalnego i są to te, które zastosowanie
defvar-local
(lub dwuskładnikowadefvar
/make-variable-buffer-local
, który jest za krótki, głównie w starszych kod przed skrótem dodano). To sprawia, że jest buforowy lokalnie we wszystkich buforach. W przypadku niektórych zmiennych ich pierwotne zastosowanie nie jest lokalne dla bufora, ale z jakiegoś powodu możesz chcieć, aby jeden bufor miał inną wartość. To wtedy używaszmake-local-variable
, zwykle w jakimś kodzie konfiguracji bufora prawie nigdy zaraz podefvar
.I ogólnie rzecz biorąc,
defvar
formularze mają dwa cele . Jednym z nich jest posiadanie dokumentacji, która C-h vmoże być wykorzystana przez innych, aby dowiedzieć się, do czego służy zmienna. Drugim jest zadeklarowanie wartości „domyślnej”, aby zmienna była zawsze ustawiona. Deklaracja wartości domyślnej wpływa tylko na globalną (lub domyślną) instancję zmiennej i jest używana tylko wtedy, gdy ta instancja nie jest już ustawiona na coś. Oznacza to, że jeśli wprowadziszsetq
jakąś zmienną, a następnie dodasz plik dodefvar
(np. Przez arequire
), defvar nie zmieni wartości.¹ Dokładniej,
defvar
nie modyfikuje wartości zmiennej, jeśli jest już ustawiona (ustawia jednak dokumentację); oznacza to, że plik inicjujący użytkownika może to zrobić(setq some-variable)
przed załadowaniem pakietu, aby zastąpić domyślną wartość pakietu.źródło
set-local
mówi czytelnikom, że ustawiana jest lokalna zmienna. Wszystko, co mogę zrobić, aby poprawić czytelność mojego kodu, jest dobre! PS. Spróbuję częściej przechodzić do źródła; na moim obecnym poziomie rozwoju często tak naprawdę nie zajmuje się semantyką ... :-)defvar
dla każdej zmiennej globalnej” nie jest ściśle poprawne - zdarzają się sytuacje, w których(defvar VARNAME)
bez wartości należy zadeklarować, niezależnie od właściwej definicji (o wartości początkowej i najlepiej dokumentacji) tej zmiennej.setq-local
idefvar-local
zostały wprowadzone tylko w Emacs 24.3.(defvar varname)
należy zadeklarować bez wartości? Myślę, że właśnie to zasugerował Drew w innym wątku, gdy pytałem, jak pozbyć się bezpłatnych ostrzeżeń o zmiennych w moich plikach dla globali, które zadeklarowałem gdzie indziej. Robię to teraz. Czy o takiej sytuacji mówisz?C-h i g (elisp) Warning Tips
). Drugi dotyczy bibliotek wykorzystujących wiązanie leksykalne, aby zapewnić (jeśli to konieczne), że zmienna jest dynamicznie związana, a nie leksykalnie.