eval-when-compile: defsubst vs defmacro vs define-inline

8

Ich habe in init.el einige einfache Funktionen definiert, zum Beispiel my-cache-file:

(defconst my-cache-directory
  (expand-file-name ".cache" user-emacs-directory)) ; ~/.emacs/.cache

(defun my-cache-file (x)
  (expand-file-name x my-cache-directory))          ; ~/.emacs/.cache/x

(setq savehist-file
      (my-cache-file "savehist"))

(setq backup-directory-alist
      `(("." . ,(my-cache-file "backups/"))))

Dies schien ein guter Anwendungsfall für defsubst:

(defsubst my-cache-file (x) ...)

Dann fing ich an, etwas über Kompilierung zu lernen und wollte weiter optimieren. Ich habe naiv versucht:

(defsubst my-cache-file (x)
  (eval-when-compile (expand-file-name x my-cache-directory)))

aber der Compiler hat sich (zu Recht) über die freie Variable beschwert x, also habe ich stattdessen den aufrufenden Code verpackt:

(setq savehist-file
      (eval-when-compile (my-cache-file "savehist")))

(setq backup-directory-alist
      `(("." . ,((eval-when-compile (my-cache-file "backups/"))))

Dieser letzte Aufrufer sollte jedoch wahrscheinlich die gesamte Liste zur Kompilierungszeit auswerten, also habe ich Folgendes aufgerufen eval-when-compile:

(setq backup-directory-alist
      (eval-when-compile `(("." . ,(my-cache-file "backups/")))))

Ich möchte vermeiden, meinen Code mit mehr eval-when-compileAufrufen als nötig zu verunreinigen , und ich frage mich, ob es einen besseren Ansatz gibt, den ich mit Makros oder verwenden könnte define-inline. Die Dokumentation macht define-inlinevielversprechend:

Über define-inline definierte Funktionen haben mehrere Vorteile in Bezug auf Makros, die durch defsubst oder defmacro definiert sind:

  • Sie können an mapcar übergeben werden (siehe Zuordnungsfunktionen).
  • Sie sind effizienter.
  • Sie können als Ortsformulare zum Speichern von Werten verwendet werden (siehe Generalisierte Variablen).
  • Sie verhalten sich vorhersehbarer als cl-defsubst (siehe Argumentlisten in allgemeinen Lisp-Erweiterungen für GNU Emacs Lisp).

Aber die Syntax sieht umständlich aus, und ich kann kein einziges Beispiel dafür finden, wie sie in freier Wildbahn verwendet wird. Ich kann auch keine Erklärung für die Behauptung finden, dass defsubst weniger effizient ist.

Hat jemand etwas verwendet define-inlineoder gibt es ein anderes Makro, das ich untersuchen sollte, oder sollte ich einfach dabei bleiben defsubst?

ivan
quelle

Antworten:

6

Ich würde sagen, bleib bei defun.

Wenn Sie versuchen möchten define-inline, was neu ist (es hat noch nicht einmal eine Dokumentzeichenfolge!), Fahren Sie fort.

Aber denken Sie darüber nach, wie viel Sie Inlining wollen oder brauchen. Es ist selten, es zu brauchen, IMO (sicherlich nicht für die Art von Dingen, die Sie hier zeigen, aber sie sind zweifellos nur, um die Frage zu vermitteln).

Ich würde definitiv empfehlen, nicht zu verwenden defsubst. Sie brauchen es wahrscheinlich nicht und es steht Ihnen nur im Weg. Es könnte 1985 einen Anwendungsfall gehabt haben, aber ich kenne keinen Ort, an dem es jetzt nützlich ist. define-inlineist anscheinend ein Versuch, den Vorteil defsubstohne den Nachteil zu nutzen.

Diese Frage könnte in erster Linie meinungsbasiert sein. Diese Antwort ist auf jeden Fall nur eine Meinung.

Drew
quelle
Gute Antwort, danke! Sie haben Recht, ich habe ein einfaches Beispiel gewählt, hauptsächlich aus Gründen der Klarheit. Ich bin neugierig, eine defmacrooder eine define-inlineLösung zu versuchen , also werde ich sie wahrscheinlich versuchen . Es wäre schön, eval-when-compilein den resultierenden Ausdruck eingebrannt zu haben .
Ivan