Jak działa scoping w emacs lisp
Wiele konfiguracji emacsa udostępnianych publicznie ma następujący format:
;; 01-something.el
(provide 'something)
;; init.el
(require 'something)
Załóżmy, że piszę plik defun o nazwie „s-join” wewnątrz 01-something.el
Przypuśćmy, że gdzieś podczas inicjalizacji init.el ładuje się magit.el s.el- popularny pakiet narzędzi tekstowych, który również ma plik defun o nazwie „s-join”
Więc teraz, w danym kontekście, skąd mam wiedzieć, co jest wykonywane, kiedy to robię
(s-join)
?
Odpowiedzi
Wszystkie funkcje i zmienne zdefiniowane w ładowanym pliku są umieszczane w środowisku globalnym. Chociaż Emacs ma pakiety do zainstalowania, nie są one w żaden sposób odizolowane od siebie. Jeśli dwa pliki definiują funkcje lub zmienne o tej samej nazwie, otrzymasz ostrzeżenie po załadowaniu drugiego.
Możesz dowiedzieć się, gdzie funkcja została zdefiniowana, prosząc o pomoc dotyczącą funkcji z C-h f. Wyświetli monit o podanie nazwy funkcji. Jeśli tekst w punkcie wygląda jak prawidłowy identyfikator lisp, a funkcja o tej nazwie istnieje, ten identyfikator będzie wartością domyślną monitu. C-h vzrobi to samo dla zmiennych. C-h Fprosi o podanie nazwy funkcji i przenosi do strony informacyjnej, na której jest udokumentowana ta funkcja, która może zawierać bardziej szczegółowe informacje.
W Elisp wszystkie nazwy funkcji normalnie (ale niekoniecznie) znajdują się jako wpisy w środowisku globalnym (obarray). W Elisp funkcje można przedefiniować. Oznacza to, że definicja funkcji, która została oceniona (lub załadowana) jako ostatnia, będzie jedyną, która jest znana i używana.
W ten sposób możesz zmieniać funkcje w swoim pliku init, po prostu musisz mieć pewność, że definicja funkcji jest oceniana po funkcji, którą chcesz zmienić.
Ale strzeż się! Jeśli oryginalna funkcja zmienia zachowanie lub parametry, twoja nie zmienia się automatycznie, a więc funkcje zależne mogą zawieść lub źle działać.
Odpowiadając na poniższe komentarze, aby dowiedzieć się, jak uniknąć niepowodzenia w korzystaniu z kodu źródłowego.
- powinieneś wybrać nazwę funkcji, która jest unikalna dla twojej własnej funkcji, aby temu zapobiec (tj. przedrostek nazwy funkcji)
- możesz napisać straż wokół swojej funkcji, aby zapobiec nadpisaniu definicji funkcji jakiejś istniejącej funkcji (to nie pomoże, jeśli twoja funkcja zostanie nadpisana, zobacz następny punkt)
(unless (fboundp 's-join)
(defun s-join ()
...))
- możesz użyć
advicew swojej funkcji i tam sprawdzić charakterystykę swojej funkcji (tj. parametry lub pierwszy seks w ciele, itp.). Porady IMO pozostają na miejscu nawet wtedy, gdy funkcja zostanie przedefiniowana.
Wydaje się, że OP nie rozumie celu, o którym już wyraźnie mowa w dwóch udzielonych odpowiedziach: nie możesz zrobić tego, o co prosisz. Emacs do definiowania przestrzeni nazw używa dobrowolnej konwencji nazewnictwa, a nie reguł składni lub kompilacji. Brzmi to jak przepis na chaos, ale w praktyce sprawdza się bardzo dobrze.
To, co robisz, gdy nazywasz swoją funkcję, s-join(skutecznie) kradnie sprefiks identyfikujący przestrzeń nazw pakietu, co jest sprzeczne z konwencją. Nie rób tego. Nazwij swoją funkcję anw/join-stringslub podobną, jak zasugerowano powyżej.
Jeśli naprawdę, naprawdę potrzebujesz tymczasowo zastąpić istniejącą funkcję, możesz użyć cl-fletlub cl-labels. Zobacz węzeł Info dla pakietu CL.