Tại sao `eval-when-compile` chạy khi tải tệp và được biên dịch byte thành .elc?


9

Thành ngữ phổ biến để giải quyết mở rộng macro hoặc giải quyết cảnh báo về các biến không xác định trong quá trình biên dịch byte:

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

Nhưng điều này require ...được biên soạn thành .elctập tin! Tôi thấy rằng cl-eval-whencó ngữ nghĩa thích hợp (theo tên).

Thông thường chúng tôi không cần requirelàm tệp trang web vàpackage.el

Ví dụ: tôi muốn biên dịch byte của tôi .emacs, sử dụng một số macro bên ngoài, nhưng âm thầm chuyển qua nếu không có gói như vậy:

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

Một cách khác để làm điều này là:

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

Nhưng bây giờ chúng tôi không phải là một hình thức cấp cao nhất ...

Tôi có điền đúng eval-when-compiletên đó để làm điều gì đó không được mong đợi từ tên của nó không?


FWIW, hai đoạn sau không có hành vi giống nhau. Các cựu không bảo vệ w3m-DEPENDENT-CODEkhỏi mất tích w3m-util.
vẽ

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

(when (require 'w3m-util nil t) ...)là thành ngữ tốt đẹp! Nhưng tôi cố gắng tạo ra một .emacstập tin hoàn hảo , không phải là một thư viện. Vì vậy, hãy nhớ tải mã chậm (theo yêu cầu) với sự trợ giúp của tự động tải. Vì lý do này, tôi sử dụng rộng rãi eval-after-load, chỉ yêu requirecầu để tạo thành công biên dịch byte với mở rộng macro.
gavenkoa

Câu trả lời:


9

Bạn có hỏi Emacs eval-when-compilephải làm gì không?

C-h f eval-when-compile cho bạn biết rằng nó cũng đánh giá arg trong thời gian tải:

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.

Nó nói rằng nếu giải thích nó là như thế progn. Và nó rõ ràng lặp lại điều này.

Một hàm hoặc tên macro hiếm khi phản ánh hành vi một cách hoàn hảo. Nhưng trong trường hợp này có vẻ như bạn đang tìm kiếm một hành vi khác, có thể được gọi eval-only-when-compile.


1
eval-only-when-compileTên giúp tôi hiểu điểm để tên eval-when-compile, cảm ơn!
gavenkoa

3

Để đánh giá mã chỉ trong giai đoạn biên dịch, hãy sử dụng các eval-whenmacro được RMS đề ngày vào năm 1993-07-30.

cl-eval-when đã xuất hiện vào 2012-06-03 từ Stefan Monnier và nó không có sẵn cho Emacs 22.x (nếu bạn quan tâm, tôi làm).

Ví dụ bạn muốn thoát khỏi Warning: assignment to free variable:

(setq auto-revert-interval 2)

chỉ cần thêm vào trên dòng đó:

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

Lưu ý rằng điều này chỉ hữu ích cho việc biên dịch byte .emacstệp. Nếu bạn phát triển thư viện, bạn nên làm requirehoặc tách tệp thư viện thành các tính năng riêng biệt và chỉ tải các tính năng cần thiết.


Để tránh các cảnh báo khác nhau, bạn chỉ cần(defvar auto-revert-interval)
npostavs

1
Tôi sử dụng defvargiải pháp trong nhiều trường hợp nhưng cũng tìm kiếm giải pháp mạnh hơn . Tôi có thể gõ nhầm tên hoặc gói có thể xóa định nghĩa và trình kiểm tra biên dịch sẽ im lặng trong các trường hợp như vậy.
gavenkoa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.