Mit der Hinweisfunktion können Sie das Verhalten einer Funktion global ändern. Eine Hinweisdefinition kann die ursprüngliche Funktion aufrufen.
(defadvice foo
(around foo-bar activate compile)
"Always set `qux' to t when running `foo'."
(let ((qux t))
ad-do-it))
Das cl
Paket enthält das flet
Makro zum lokalen Überschreiben einer Funktion.
(defun foo ()
"global")
(flet ((foo ()
"local"))
(some-code-that-calls-foo))
Das erlaubt keinen Verweis auf die ursprüngliche foo
Funktion. Was ist, wenn die lokale Überschreibung die ursprüngliche Funktion aufrufen muss?
(defun foo ()
"global")
(flet ((foo ()
(concat (foo) "+local")))
;; this will cause an infinite loop when (foo) is called
(some-code-that-calls-foo))
Dieser einfache Ansatz funktioniert aus gutem Grund nicht: Er (foo)
ist ein rekursiver Aufruf der lokalen Definition.
Was ist eine nicht umständliche Methode zum lokalen Überschreiben einer Funktion, mit der die ursprüngliche Funktion aus dem Überschreibungscode aufgerufen werden kann?
Anwendung: Affen-Patching eines vorhandenen Codes, in einem Fall, in dem foo
nicht global zurückgebunden werden sollte, der Code jedoch das Original aufrufen muss. Hier ist das neueste Beispiel, das ich wollte:
(defadvice TeX-master-file
(around TeX-master-file-indirect-buffer activate compile)
"Support indirect buffers."
(flet ((buffer-file-name (&optional buffer)
(<global buffer-file-name> (buffer-base-buffer buffer))))
ad-do-it)))
Ich wollte buffer-file-name
lokal neu binden und das Original aufrufen buffer-file-name
. Ok, in diesem speziellen Fall gibt es eine Problemumgehung, bei der die buffer-file-name
Variable verwendet wird. Aber der Punkt meiner Frage hier ist die allgemeine Technik. Wie kann ich eine Funktion (hier buffer-file-name
) lokal binden, aber die globale Definition aus meiner Neudefinition aufrufen?
Dies ist für meine .emacs
, die ich weiterhin in Emacs 19.34 arbeite, sodass Lösungen, die Emacs 24.4 erfordern, nicht verfügbar sind. Ich bevorzuge zwar Lösungen, die mit lexikalischer Bindung sauber umgehen - aber beim Affen-Patching geht es von Natur aus um dynamische Bindung.
cl-letf
in Emacs 24.3 und früher verfügbar ist, aber hier ist eine verwandte Frage