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


8

Definí algunas funciones simples en init.el, por ejemplo 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 parecía un buen caso de uso para defsubst:

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

Luego comencé a aprender sobre compilación y quería optimizar aún más. Intenté ingenuamente:

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

pero el compilador se quejó (correctamente) sobre la variable libre x, por lo que envolví el código de llamada:

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

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

Sin embargo, la última persona que llama probablemente debería estar evaluando toda la lista en tiempo de compilación, así que eval-when-compilelevanté:

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

Me gustaría evitar ensuciar mi código con más eval-when-compilellamadas de las necesarias, y me pregunto si hay un mejor enfoque que pueda tomar usando macros o define-inline. La documentación marcas define-inlinesonido prometedor:

Las funciones definidas mediante define-inline tienen varias ventajas con respecto a las macros definidas por defsubst o defmacro:

  • Se pueden pasar a mapcar (ver Funciones de mapeo).
  • Son mas eficientes.
  • Se pueden usar como formularios de lugar para almacenar valores (consulte Variables generalizadas).
  • Se comportan de una manera más predecible que cl-defsubst (ver Listas de argumentos en extensiones Common Lisp para GNU Emacs Lisp).

Pero la sintaxis parece engorrosa, y no puedo encontrar un solo ejemplo de su uso en la naturaleza. Tampoco puedo encontrar ninguna explicación de su afirmación de que defsubst es menos eficiente.

¿Alguien ha usado define-inline, o hay una macro diferente que debería analizar, o debería seguir defsubst?

Respuestas:


6

Yo diría que te quedes defun.

Si quieres probar define-inline, que es nuevo (¡ni siquiera tiene una cadena de documentos todavía!), Adelante.

Pero piense en cuánto quiere o necesita en línea. Es raro que lo necesite, OMI (ciertamente no para el tipo de cosas que muestra aquí, pero sin duda son solo para hacer la pregunta).

Definitivamente recomendaría no usar defsubst. Probablemente no lo necesite, y simplemente se interpone en el camino. Podría haber tenido un caso de uso en 1985, pero no conozco ningún lugar donde sea útil ahora. define-inlineAparentemente es un intento de obtener el beneficio defsubstsin la desventaja.

Esta pregunta podría estar basada principalmente en la opinión. Esta respuesta es solo una opinión, en cualquier caso.


Buena respuesta, gracias! Tienes razón, elegí un ejemplo simple principalmente por razones de claridad. Tengo curiosidad por probar una defmacroo una define-inlinesolución, así que probablemente las apuñalaré. Sería bueno haber eval-when-compilecocido en la expresión resultante.
ivan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.