eval-when
的必需用途是爲了確保在編譯和使用宏時,宏所依賴的函數是可用的。但是,我想不出一個能證明不使用eval-when
的後果的例子。在Common Lisp中,您何時需要使用eval-when,以及您如何知道?
(defpackage :eval-when
(:use :cl))
(in-package :eval-when)
(defun util-fun (x) (* x x))
(defmacro needs-help (x) `(let ((a (util-fun ,x))) a))
;; use it in the same file
(defun use-the-macro (x) (needs-help x))
(use-the-macro 5)
如果我理解正確的(defun util-fun ...)
應eval-when
包裹。
編輯:正如你從應答看到,還有這個例子的一個問題:它實際上並沒有在編譯時調用UTIL樂趣。這解釋了爲什麼不給出錯誤,因爲它不是錯誤。但這個問題仍然有效,因爲它凸顯了新用戶的困惑。通常我使用抄送CK來評估和加載文件
; SLIME 2.19
CL-USER> (uiop:getcwd)
#P"/home/anticrisis/dev/common-lisp/eval-when/"
CL-USER> (compile-file "eval-when.lisp")
; compiling file "/home/anticrisis/dev/common-lisp/eval-when/eval-when.lisp" (written 14 AUG 2017 11:30:49 AM):
; compiling (DEFPACKAGE :EVAL-WHEN ...)
; compiling (IN-PACKAGE :EVAL-WHEN)
; compiling (DEFUN UTIL-FUN ...)
; compiling (DEFMACRO NEEDS-HELP ...)
; compiling (DEFUN USE-THE-MACRO ...)
; compiling (USE-THE-MACRO 5)
; /home/anticrisis/dev/common-lisp/eval-when/eval-when.fasl written
; compilation finished in 0:00:00.009
#P"/home/anticrisis/dev/common-lisp/eval-when/eval-when.fasl"
NIL
NIL
CL-USER> (in-package :eval-when)
#<PACKAGE "EVAL-WHEN">
EVAL-WHEN> (use-the-macro 3)
; Evaluation aborted on #<UNDEFINED-FUNCTION USE-THE-MACRO {10035E1103}>.
EVAL-WHEN> (needs-help 4)
; Evaluation aborted on #<UNDEFINED-FUNCTION UTIL-FUN {100387FE33}>.
EVAL-WHEN> (load "eval-when.lisp")
T
EVAL-WHEN> (use-the-macro 3)
9
EVAL-WHEN> (needs-help 4)
16
EVAL-WHEN>
注:
然而,從REPL,沒有錯誤或警告在編譯過程中,負載或使用(SBCL 1.3.20)發佈到repl,但在這裏,我使用compile-file
和load
命令來證明沒有錯誤發生。 (當我在編譯之後但在加載之前嘗試使用這些函數時,我確實收到錯誤,但是這會在任何卸載代碼時發生。)
有以下問題和意見涉及到:
這previous StackOverflow answer似乎很清楚地說,這是用來由宏任何功能必須由
eval-when
形式被封閉,或者在一個單獨的文件中加載。從信息轉儲這一評論也很明確:
當宏展開時,該宏調用必須 定義的任何功能。如果您有一個編譯單元定義了一個宏,其中的 稱爲函數,但實際上並沒有在同一個編譯單元中使用該宏,則不需要eval-when。但是,如果您定義了一個 aux。函數,一個宏,並且想在你定義它之後馬上使用你的宏,那麼實現可能會抱怨aux。 功能未知 - coredump
鑑於此,爲什麼我的示例不會生成錯誤?我的例子會在其他情況下失敗嗎?如果沒有正確使用eval-when
會產生編譯時,加載時或運行時錯誤,這將有助於我的理解。
謝謝你的耐心等待!
你可能想看看這個問題https://stackoverflow.com/questions/10674650/eval-when-uses。您也可以閱讀PCL的eval-when部分http://www.gigamonkeys.com/book/the-special-operators.html –
@DavidHodge感謝您的推薦;我已經將我的問題擴大到更具體。 – anticrisis
你提到的另一個答案是關於編譯文件的討論。你提到一個REPL。這是兩回事。還請發佈具體問題,最好用代碼。 –