Perché `eval-when-compile` viene eseguito al caricamento del file e compilato in byte in .elc?


9

Idioma comune per aggirare l'espansione di macro o risolvere avvisi relativi a variabili non definite durante la compilazione di byte:

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

Ma questo è stato require ...compilato in un .elcfile! Ho scoperto che cl-eval-whenhanno una semantica corretta (in base al nome).

Normalmente non abbiamo bisogno di requirecome file del sito epackage.el

Ad esempio, voglio compilare byte my .emacsche utilizza alcune macro esterne, ma passano silenziosamente se non ci sono tali pacchetti:

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

Un altro modo per farlo è:

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

Ma ora non siamo un modulo di livello superiore ...

Devo riempire correttamente quel eval-when-compilenome per fare qualcosa che non è previsto dal suo nome?


FWIW, questi ultimi due frammenti non hanno lo stesso comportamento. Il primo non protegge w3m-DEPENDENT-CODEda una mancanza w3m-util.
Tracciò il

(when (require 'w3m-util nil t) (w3m-util-DEPENDENT-CODE...))
Tracciò il

(when (require 'w3m-util nil t) ...)è un bel linguaggio! Ma provo a creare un .emacsfile perfetto , non una libreria. Quindi, ricorda il caricamento ritardato (su richiesta) del codice con l'aiuto del caricamento automatico. Per questo motivo che utilizzo ampiamente eval-after-load, mi è stato chiesto requiresolo di avere successo con la compilazione di byte con l'espansione delle macro.
gavenkoa,

Risposte:


9

Hai chiesto a Emacs cosa eval-when-compiledovrebbe fare?

C-h f eval-when-compile ti dice che valuta l'arg anche al momento del caricamento:

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 che se interpretato è come progn. E lo ripete esplicitamente.

Raramente un nome di funzione o macro riflette perfettamente il comportamento. Ma in questo caso sembra che tu stia cercando un comportamento diverso, che potrebbe essere chiamato eval-only-when-compile.


1
eval-only-when-compilenome aiutami a capire punto per nome eval-when-compile, grazie!
gavenkoa,

3

Per valutare il codice solo in fase di compilazione, utilizzare le eval-whenmacro datate da RMS nel periodo 1993-07-30.

cl-eval-when è apparso nel 03/06/2012 da Stefan Monnier e non è disponibile per Emacs 22.x (se ti interessa, lo faccio).

Ad esempio ti piace sbarazzarti di Warning: assignment to free variablein:

(setq auto-revert-interval 2)

basta aggiungere sopra quella riga:

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

Si noti che questo è utile solo per la compilazione di byte di .emacsfile. Se sviluppi una libreria dovresti fare requireo dividere il file della libreria in separato e caricare solo le funzionalità richieste.


Per evitare avvisi variabili, è sufficiente(defvar auto-revert-interval)
npostavs

1
Uso la defvarsoluzione in molti casi, ma cerco anche una soluzione più forte . Posso digitare male il nome o il pacchetto può rimuovere la definizione e il correttore di compilazione sarebbe silenzioso in questi casi.
gavenkoa,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.