我正在閱讀有關CLOS的維基百科文章。
它說:
這種分派機制在運行時起作用。因此,添加或洗掉方法可能會導致在運行時更改有效方法(即使使用相同的引數呼叫泛型函式)。改變方法組合也可能導致不同的有效方法。
然后,我插入:
; declare the common argument structure prototype
(defgeneric f (x y))
; define an implementation for (f integer t), where t matches all types
(defmethod f ((x integer) y) 1)
使用 SBCL 和 SLIME,我用代碼編譯了這些區域,得到了以下結果:
CL-USER> (f 1 2)
1
然后,我添加到定義中:
; define an implementation for (f integer real)
(defmethod f ((x integer) (y real)) 2)
再次,我重復了編譯新區域并使用 REPL 進行評估的程序:
CL-USER> (f 1 2.0)
2
第一個問題,如果 CLOS 具有與運行時分派相反的行為(我想是編譯時分派),結果會是什么?
第二個問題,我決定把第二種方法注釋掉,只留下泛型函式和第一種寫法。然后,我用 Emacs 重新編譯了該區域。
當呼叫fREPL 中的函式時,(f 1 2)我想我會得到1,因為第二種方法已經出來了。相反,我得到了2.
CL-USER> (f 1 2.0)
2
為什么會這樣?
我可以(f 1 2)回傳的唯一方法1是重新啟動 Slime REPL 并編譯該區域(第二種方法被注釋掉)。第三個問題,有沒有更好的方法來獲得這個結果而不必重新啟動 REPL?
謝謝!
uj5u.com熱心網友回復:
這兩個其實是同一個問題。答案是:您正在修改一個正在運行的系統。
如果 CLOS 物件在運行時不能重新定義,這根本就行不通,或者你不被允許這樣做。嘗試使用基本結構(即使用 時得到的東西)進行此類重新定義,
defstruct當更改不兼容時,您經常會遇到非常嚴重的警告甚至錯誤。當然,結構體也有其他限制,例如只能單次分派,因此制作一個完全類似的示例并不容易。但是嘗試從 defstruct 中洗掉一個插槽。僅僅注釋掉一些源代碼并不會改變您之前評估(編譯和加載)它的事實。您正在操縱一個正在運行的系統,而源代碼就是:source。如果要從正在運行的系統中洗掉方法,可以使用
remove-method(另請參閱如何洗掉結構的 defmethod)。大多數 Lisp IDE 都有辦法以互動方式執行此操作,例如在 SLIME 中使用 SLIME 檢查器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/438749.html
