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

8

Eu defini algumas funções simples no init.el, por exemplo 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/"))))

Este parecia ser um bom caso de uso para defsubst:

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

Então comecei a aprender sobre compilação e queria otimizar ainda mais. Tentei ingenuamente:

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

mas o compilador reclamou (com razão) sobre a variável livre x, então envolvi o código de chamada:

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

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

Porém, esse último chamador provavelmente deveria estar avaliando todo o alist em tempo de compilação, então resolvi eval-when-compile:

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

Eu gostaria de evitar encher meu código com mais eval-when-compilechamadas do que o necessário, e me pergunto se há uma abordagem melhor que eu possa usar usando macros ou define-inline. A documentação faz define-inlineparecer promissor:

As funções definidas via define-inline têm várias vantagens em relação às macros definidas por defsubst ou defmacro:

  • Eles podem ser passados ​​para o mapcar (consulte Funções de mapeamento).
  • Eles são mais eficientes.
  • Eles podem ser usados ​​como formulários de local para armazenar valores (consulte Variáveis ​​generalizadas).
  • Eles se comportam de uma maneira mais previsível do que cl-defsubst (consulte Listas de argumentos nas extensões Common Lisp para GNU Emacs Lisp).

Mas a sintaxe parece complicada e não consigo encontrar um único exemplo disso sendo usado na natureza. Também não consigo encontrar nenhuma explicação para a afirmação de que defsubst é menos eficiente.

Alguém já usou define-inline, ou existe uma macro diferente em que devo examinar ou devo ficar com defsubst?

ivan
fonte

Respostas:

6

Eu diria que fique com defun.

Se você quiser experimentar define-inline, o que é novo (ele ainda nem tem uma sequência de documentos!), Vá em frente.

Mas pense em quanto você deseja ou precisa ser incorporado. É raro precisar dele, IMO (certamente não para o tipo de coisa que você mostra aqui, mas eles são sem dúvida apenas para esclarecer a questão).

Eu recomendaria definitivamente não usar defsubst. Você provavelmente não precisa, e isso apenas atrapalha. Pode ter tido um caso de uso em 1985, mas não conheço nenhum lugar onde seja útil agora. define-inlineaparentemente é uma tentativa de obter o benefício defsubstsem a desvantagem.

Esta questão pode ser principalmente baseada em opiniões. Esta resposta é apenas uma opinião, em qualquer caso.

Desenhou
fonte
Boa resposta, obrigado! Você está certo, eu escolhi um exemplo simples principalmente por uma questão de clareza. Estou curioso para tentar uma defmacroou define-inlinesolução, então provavelmente vou dar uma facada neles. Seria bom ter eval-when-compileinserido a expressão resultante.
ivan