¿Por qué `eval-when-compile` se ejecuta al cargar el archivo y se compila en bytes a .elc?

9

Idioma común para solucionar la expansión de macros o resolver advertencias sobre variables indefinidas durante la compilación de bytes:

(eval-when-compile
  (require 'cl-lib))

Pero esto require ...compilado en .elcarchivo! Encontré que cl-eval-whentienen una semántica adecuada (según el nombre)

Normalmente no necesitamos requirecomo archivo de sitio ypackage.el

Por ejemplo, quiero compilar en bytes mi .emacsque usa algunas macros externas, pero pasar silenciosamente si no hay tal paquete:

(cl-eval-when 'compile
  (condition-case err
      (require 'w3m-util)
    (error (byte-compile-warn "Failed by: %S" err))))
(w3m-util-DEPENDENT-CODE ...)

Otra forma de hacer esto es:

(ignore-error
   (require 'w3m-util)
   (w3m-util-DEPENDENT-CODE ...))

Pero ahora no somos una forma de nivel superior ...

¿Relleno correctamente ese eval-when-compilenombre y hago algo que no se espera de su nombre?

gavenkoa
fuente
FWIW, los dos últimos fragmentos no tienen el mismo comportamiento. El primero no protege w3m-DEPENDENT-CODEde los desaparecidos w3m-util.
Dibujó el
(when (require 'w3m-util nil t) (w3m-util-DEPENDENT-CODE...))
Dibujó el
(when (require 'w3m-util nil t) ...)es un buen idioma! Pero trato de hacer un .emacsarchivo perfecto , no una biblioteca. Por lo tanto, tenga en cuenta la carga de código retrasado (a pedido) con la ayuda de la carga automática. Por esta razón, uso mucho eval-after-load, requiresolo se necesita para que la compilación de bytes tenga éxito con la expansión de macros.
gavenkoa

Respuestas:

9

¿Le preguntaste a Emacs qué eval-when-compilese supone que debe hacer?

C-h f eval-when-compile le dice que evalúa el argumento también en el momento de la carga:

eval-when-compile is a Lisp macro in `byte-run.el'.

(eval-when-compile &rest BODY)

Like ‘progn’, but evaluates the body at compile time if you’re compiling.
Thus, the result of the body appears to the compiler as a quoted
constant.  In interpreted code, this is entirely equivalent to
‘progn’, except that the value of the expression may be (but is
not necessarily) computed at load time if eager macro expansion
is enabled.

Dice que si se interpreta es como progn. Y explícitamente repite esto.

Un nombre de función o macro rara vez refleja el comportamiento perfectamente. Pero en este caso, parece que está buscando un comportamiento diferente, que podría llamarse eval-only-when-compile.

Dibujó
fuente
1
eval-only-when-compilenombre ayúdame a entender punto a nombre eval-when-compile, gracias!
gavenkoa
3

Para evaluar el código solo en la etapa de compilación, use eval-whenmacros fechadas por RMS en 1993-07-30.

cl-eval-when apareció en 2012-06-03 de Stefan Monnier y no está disponible para Emacs 22.x (si te importa, lo hago).

Por ejemplo, te gusta deshacerte de Warning: assignment to free variable:

(setq auto-revert-interval 2)

solo agregue sobre esa línea:

(eval-when 'compile (require 'autorevert))

Tenga en cuenta que esto es útil solo para la compilación de bytes del .emacsarchivo. Si desarrolla una biblioteca, debe hacer requireo dividir el archivo de la biblioteca en separado y cargar solo las características requeridas.

gavenkoa
fuente
Para evitar advertencias variables, solo necesita(defvar auto-revert-interval)
npostavs el
1
Yo uso la defvarsolución en muchos casos, pero también busco una solución más fuerte . Puedo escribir mal el nombre o el paquete puede eliminar la definición y el comprobador de compilación sería silencioso en tales casos.
gavenkoa