Mengapa `eval-when-compile` berjalan pada saat memuat file dan byte-dikompilasi ke .elc?


9

Ungkapan umum untuk mengatasi ekspansi makro atau menyelesaikan peringatan tentang variabel yang tidak ditentukan selama byte-compilation:

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

Tapi ini require ...dikompilasi menjadi .elcfile! Saya menemukan yang cl-eval-whenmemiliki semantik yang tepat (sesuai nama).

Biasanya kita tidak memerlukan requirefile situs danpackage.el

Misalnya saya ingin byte-compile saya .emacsyang menggunakan beberapa makro eksternal, tetapi diam-diam melewati jika tidak ada paket seperti itu:

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

Cara lain untuk melakukan ini adalah:

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

Tapi sekarang kita bukan bentuk tingkat atas ...

Apakah saya benar mengisi eval-when-compilenama itu melakukan sesuatu yang tidak diharapkan dari namanya?


FWIW, dua snippet terakhir tidak memiliki perilaku yang sama. Yang pertama tidak melindungi w3m-DEPENDENT-CODEdari yang hilang w3m-util.
Drew

(when (require 'w3m-util nil t) (w3m-util-DEPENDENT-CODE...))
Drew

(when (require 'w3m-util nil t) ...)adalah ungkapan yang bagus! Tapi saya mencoba membuat .emacsfile yang sempurna , bukan perpustakaan. Jadi, ingatlah untuk menunda pemuatan kode (atas permintaan) dengan bantuan pemuatan otomatis. Untuk alasan ini, saya banyak menggunakan eval-after-load, meminta requirehanya perlu membuat sukses byte-kompilasi dengan ekspansi makro.
gavenkoa

Jawaban:


9

Apakah Anda bertanya kepada Emacs apa eval-when-compileyang harus dilakukan?

C-h f eval-when-compile memberi tahu Anda bahwa ia mengevaluasi arg juga pada waktu buka:

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.

Dikatakan bahwa jika ditafsirkan itu seperti progn. Dan itu secara eksplisit mengulang ini.

Fungsi atau nama makro jarang mencerminkan perilaku dengan sempurna. Tetapi dalam hal ini sepertinya Anda mencari perilaku yang berbeda, yang mungkin disebut eval-only-when-compile.


1
eval-only-when-compilenama bantu saya mengerti point to name eval-when-compile, terima kasih!
gavenkoa

3

Untuk mengevaluasi kode hanya pada tahap kompilasi, gunakan eval-whenmacro yang diberi tanggal oleh RMS pada 1993-07-30.

cl-eval-when muncul di 2012-06-03 dari Stefan Monnier dan tidak tersedia untuk Emacs 22.x (jika Anda peduli, saya tahu).

Misalnya, Anda ingin menyingkirkan Warning: assignment to free variable:

(setq auto-revert-interval 2)

tambahkan saja di atas baris itu:

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

Perhatikan bahwa ini hanya berguna untuk kompilasi byte .emacsfile. Jika Anda mengembangkan perpustakaan, Anda harus melakukan requireatau membagi file perpustakaan menjadi terpisah dan memuat hanya fitur yang diperlukan.


Untuk menghindari peringatan yang bervariasi, Anda hanya perlu(defvar auto-revert-interval)
npostavs

1
Saya menggunakan defvarsolusi dalam banyak kasus tetapi juga mencari solusi yang lebih kuat . Saya bisa salah ketik nama atau paket dapat menghapus definisi dan pemeriksa kompilasi akan diam dalam kasus seperti itu.
gavenkoa
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.