Wszystkie potrzebne informacje są zawarte w tym, C-h f add-function
który opisuje podstawowy mechanizm advice-add
.
Nowy system porad działa w zasadzie jak zastąpienie bieżącej definicji funkcji funkcją opisaną w tabeli, w
C-h f add-function
zależności od wyboru WHERE
argumentu, czystsze tylko w celu śledzenia, jakie zachowanie zostało zdefiniowane w danym pliku źródłowym.
Przykład z :around
opcją
Najbardziej ogólnym przypadkiem jest :around
opcja, więc podaję na to przykład. (Prawdopodobnie lepiej jest użyć dedykowanych WHERE
parametrów, jeśli to możliwe, ale można zastąpić się równoważnymi
:around
funkcjami).
Na przykład, powiedzmy, że chcesz debugować użycie find-file
i print
listę argumentów za każdym razem, gdy jest wywoływana. Mógłbyś pisać
(defun my-find-file-advice-print-arguments (old-function &rest arguments)
"Print the argument list every time the advised function is called."
(print arguments)
(apply old-function arguments))
(advice-add #'find-file :around #'my-find-file-advice-print-arguments)
Dzięki tej nowej implementacji wszystko, czego potrzebuje rada, jest przekazywane jako argument. ad-get-args
staje się niepotrzebny, ponieważ argumenty są przekazywane do funkcji porady jako zwykłe argumenty funkcji (dla
WHERE
argumentów, dla których ma to sens). ad-do-it
staje się niepotrzebny, ponieważ :around
rada otrzymuje jako argumenty funkcję i argumenty, dlatego (ad-do-it)
zostaje zastąpiona przez formę
(apply old-function arguments)
lub gdy podasz argumenty
(funcall old-function first-arg second-arg)
co jest czystsze, ponieważ nie ma w tym żadnych magicznych form. Modyfikacja argumentów następuje po prostu przez przekazanie zmodyfikowanych wartości do OLD-FUNCTION
.
Inne WHERE
wartości
Dokument add-function
zawiera tabelę wszystkich miejsc na porady (lub „kombinatorów”) oraz ich odpowiedników i wyjaśnia funkcjonalność w kategoriach lambda
zachowania równoważnego z zalecaną funkcją:
`:before' (lambda (&rest r) (apply FUNCTION r) (apply OLDFUN r))
`:after' (lambda (&rest r) (prog1 (apply OLDFUN r) (apply FUNCTION r)))
`:around' (lambda (&rest r) (apply FUNCTION OLDFUN r))
`:override' (lambda (&rest r) (apply FUNCTION r))
`:before-while' (lambda (&rest r) (and (apply FUNCTION r) (apply OLDFUN r)))
`:before-until' (lambda (&rest r) (or (apply FUNCTION r) (apply OLDFUN r)))
`:after-while' (lambda (&rest r) (and (apply OLDFUN r) (apply FUNCTION r)))
`:after-until' (lambda (&rest r) (or (apply OLDFUN r) (apply FUNCTION r)))
`:filter-args' (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
`:filter-return'(lambda (&rest r) (funcall FUNCTION (apply OLDFUN r)))
(cited from `C-h f add-function')
gdzie FUNKCJA jest funkcją porady, a OLDFUN funkcja, do której dodawana jest opinia. Nie próbuj zrozumieć ich wszystkich naraz, po prostu wybierz WHERE
symbol, który brzmi dobrze i spróbuj go zrozumieć.
Lub po prostu użyj :around
. O ile mogę powiedzieć jedyną zaletą korzystania specjalizuje WHERE
s nad :around
wszystkiego jest to, że można uzyskać nieco więcej informacji z patrząc C-h f ADVISED-FUNCTION
przed przeczytaniu docstring o poradę. O ile nie planujesz opublikować kodu zawierającego porady, prawdopodobnie nie ma to znaczenia.
Nazwane funkcje porad
Polecam używanie nazwanych funkcji jako porad, ponieważ zapewnia ono wiele korzyści (niektóre z nich dotyczą także używania nazwanych funkcji do przechwytywania):
Pojawia się C-h f find-file
jako
:around advice: `my-find-file-advice-print-arguments'
link do definicji funkcji porady, która jak zwykle zawiera link do pliku, w którym została zdefiniowana. Gdyby rada została zdefiniowana jako lambda
forma bezpośrednio w advice-add
formie, dokumentacja byłaby pokazana w linii (bałagan dla długich dokumentów?) I nic nie wskazywałoby, gdzie została zdefiniowana.
Możesz usunąć poradę za pomocą
(advice-remove #'find-file #'my-find-file-advice-print-arguments)
Możesz zaktualizować definicję porady bez ponownego uruchamiania
advice-add
lub ryzykowania, że stara wersja pozostanie aktywna (ponieważ uruchomienie advice-add
ze zmienioną wersją
lambda
zostanie rozpoznane jako nowa porada, a nie jako aktualizacja starej).
Side uwaga#'function
notacja jest w zasadzie równoznaczne
'function
z tym, że to pomoże kompilator bajt identyfikacji symboli jako nazw funkcji i tym samym zidentyfikować brakujące funkcje (na przykład z powodu literówek).
M-x report-emacs-bug
. Niektórzy programiści czasami wolą programować niż dokumentować. ;-) Ważne jest, aby sam Emacs dokumentował.