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


8

Ho definito alcune semplici funzioni in init.el, ad esempio 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/"))))

Sembrava un buon caso d'uso per defsubst:

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

Poi ho iniziato a conoscere la compilazione e volevo ottimizzare ulteriormente. Ho ingenuamente provato:

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

ma il compilatore si è lamentato (giustamente) della variabile libera x, quindi ho inserito il codice chiamante:

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

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

Tuttavia, l'ultimo chiamante dovrebbe probabilmente valutare l'intero elenco al momento della compilazione, quindi ho tirato eval-when-compilesu:

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

Vorrei evitare di sporcare il mio codice con più eval-when-compilechiamate del necessario e mi chiedo se c'è un approccio migliore che potrei adottare usando le macro o define-inline. La documentazione rende il define-inlinesuono promettente:

Le funzioni definite tramite define-inline presentano numerosi vantaggi rispetto alle macro definite da defsubst o defmacro:

  • Possono essere passati a mapcar (vedi Funzioni di mappatura).
  • Sono più efficienti.
  • Possono essere utilizzati come moduli di luogo per memorizzare valori (vedere Variabili generalizzate).
  • Si comportano in modo più prevedibile di cl-defsubst (vedi Elenchi di argomenti nelle estensioni Lisp comuni per GNU Emacs Lisp).

Ma la sintassi sembra ingombrante e non riesco a trovare un singolo esempio di come viene utilizzato in natura. Né posso trovare alcuna spiegazione della sua affermazione che defsubst è meno efficiente.

Qualcuno ha usato define-inlineo c'è un'altra macro che dovrei esaminare o dovrei semplicemente attenermi defsubst?

Risposte:


6

Direi di restare con defun.

Se vuoi provare define-inline, che è nuovo (non ha ancora una stringa di documenti!), Vai avanti.

Ma pensa a quanto vuoi o devi allineare. È raro averne bisogno, IMO (certamente non per il tipo di cose che mostri qui, ma non c'è dubbio solo per far passare la domanda).

Consiglio vivamente di non usare defsubst. Probabilmente non ne hai bisogno, e si mette solo in mezzo. Potrebbe aver avuto un caso d'uso nel 1985, ma non so dove sia utile adesso. define-inlineè apparentemente un tentativo di ottenere il vantaggio defsubstsenza il rovescio della medaglia.

Questa domanda potrebbe essere principalmente basata sull'opinione pubblica. Questa risposta è solo un'opinione, in ogni caso.


Buona risposta, grazie! Hai ragione, ho scelto un semplice esempio soprattutto per motivi di chiarezza. Sono curioso di provare una defmacroo una define-inlinesoluzione, quindi probabilmente mi prenderò cura di loro. Sarebbe bello aver eval-when-compileinserito l'espressione risultante.
Ivan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.