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

8

J'ai défini quelques fonctions simples dans init.el, par exemple 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/"))))

Cela semblait être un bon cas d'utilisation pour defsubst:

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

Ensuite, j'ai commencé à apprendre la compilation et je voulais optimiser davantage. J'ai naïvement essayé:

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

mais le compilateur se plaignait (à juste titre) de la variable libre x, donc à la place j'ai encapsulé le code appelant:

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

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

Ce dernier appelant devrait probablement évaluer toute la liste au moment de la compilation, alors j'ai tiré la question eval-when-compile:

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

Je voudrais éviter de salir mon code avec plus d' eval-when-compileappels que nécessaire, et je me demande s'il y a une meilleure approche que je pourrais utiliser en utilisant des macros ou define-inline. La documentation marques de define-inlineson prometteur:

Les fonctions définies via define-inline présentent plusieurs avantages par rapport aux macros définies par defsubst ou defmacro:

  • Ils peuvent être transmis à mapcar (voir Fonctions de mappage).
  • Ils sont plus efficaces.
  • Ils peuvent être utilisés comme formulaires de lieu pour stocker des valeurs (voir Variables généralisées).
  • Ils se comportent d'une manière plus prévisible que cl-defsubst (voir Listes d'arguments dans les extensions Common Lisp pour GNU Emacs Lisp).

Mais la syntaxe semble lourde, et je ne peux pas trouver un seul exemple de son utilisation dans la nature. Je ne peux pas non plus trouver d'explication à son affirmation selon laquelle defsubst est moins efficace.

Quelqu'un a-t-il utilisé define-inlineou existe-t-il une macro différente que je devrais examiner, ou devrais-je simplement rester avec defsubst?

ivan
la source

Réponses:

6

Je dirais de rester avec defun.

Si vous voulez essayer define-inline, qui est nouveau (il n'a même pas encore de chaîne de doc!), Allez-y.

Mais pensez à combien vous voulez ou avez besoin d'être inclus. Il est rare d'en avoir besoin, OMI (certainement pas pour le genre de choses que vous montrez ici, mais elles ne sont sans doute que pour faire passer la question).

Je recommanderais certainement de ne pas l'utiliser defsubst. Vous n'en avez probablement pas besoin, et cela vous gêne. Il a peut-être eu un cas d'utilisation en 1985, mais je ne connais aucun endroit où il est utile maintenant. define-inlineest apparemment une tentative de bénéficier defsubstsans inconvénient.

Cette question pourrait être principalement basée sur l'opinion. Cette réponse n'est qu'une opinion, en tout cas.

A dessiné
la source
Bonne réponse, merci! Vous avez raison, j'ai choisi un exemple simple principalement pour des raisons de clarté. Je suis curieux d'essayer une defmacroou une define-inlinesolution, alors je vais probablement essayer . Ce serait bien d'avoir eval-when-compileintégré l'expression résultante.
ivan