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?

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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.