Common lisp: Redefine an existing function within a scope? OP要求類似的東西。但是我想創建一個方法專家,而不是一個功能。 本質假設的方法是這樣定義:lisp:如何在範圍內創建臨時方法專業
defmethod my-meth ((objA classA) (objB classB)) (...)
我想什麼做的是(僞):
(labels ((my-meth ((objA classA) (objB (eql some-object)))))
do stuff calling my-meth with the object...)
真正的用途是,我想創建一個臨時的環境下,setf slot-value-using-class
將專門針對eql
,重點創建一個特定對象的按需截取其插槽寫作。 (目的是記錄舊的和新的插槽值,然後調用下一個方法。)我不想創建元類,因爲我可能想攔截已經實例化的標準對象。
當然,我嘗試了它並沒有奏效(因爲DEFMETHOD
如何在LABELS
?),但我希望一些更有經驗的人來驗證它是不可行和/或提出合適的辦法。
評論?
編輯:
丹尼爾和泰耶提供優異的鏈接,擴大我對準備知識,但我想以前去那裏多一點推動它在尋找一個更香草的方法。我一直在考慮在進入環境時進行add-method,這將專注於eql,並在退出時執行remove-method。我還沒有完成。如果有人玩過這些,評論會很好。將保持線程是最新的。
編輯2:我接近做與添加方法的場景,但有一個問題。這是我曾嘗試:
(defun inject-slot-write-interceptor (object fun)
(let* ((gf (fdefinition '(setf sb-mop:slot-value-using-class)))
(mc (sb-mop:generic-function-method-class gf))
(mc-instance (make-instance (class-name mc)
:qualifiers '(:after)
:specializers (list (find-class 't)
(find-class 'SB-PCL::STD-CLASS)
(sb-mop::intern-eql-specializer object)
(find-class 'SB-MOP:STANDARD-EFFECTIVE-SLOT-DEFINITION))
:lambda-list '(new-value class object slot)
:function (compile nil (lambda (new-value class object slot) (funcall fun new-value class object slot))))))
(add-method gf mc-instance)
(defun remove-slot-write-interceptor()
(remove-method gf mc-instance))
))
(defun my-test (object slot-name data)
(let ((test-data "No results yet")
(gf (fdefinition '(setf sb-mop::slot-value-using-class))))
(labels ((show-applicable-methods() (format t "~%Applicable methods: ~a" (length (sb-mop:compute-applicable-methods gf (list data (class-of object) object (slot-def-from-name (class-of object) slot-name)))))))
(format t "~%Starting test: ~a" test-data)
(show-applicable-methods)
(format t "~%Injecting interceptor.")
(inject-slot-write-interceptor object (compile nil (lambda (a b c d) (setf test-data "SUCCESS !!!!!!!"))))
(show-applicable-methods)
(format t "~%About to write slot.")
(setf (slot-value object slot-name) data)
(format t "~%Wrote slot: ~a" test-data)
(remove-slot-write-interceptor)
(format t "~%Removed interceptor.")
(show-applicable-methods)
)))
一些對象插槽和數據
調用(我的測試)爲ARGS結果:
Starting test: No results yet
Applicable methods: 1
Injecting interceptor.
Applicable methods: 2
About to write slot.
Wrote slot: No results yet <----- Expecting SUCCESS here....
Removed interceptor.
Applicable methods: 1
所以我在這裏停留。因爲適用的方法現在包含eql-specialized:after方法,所以專門化可以工作,但不幸的是它似乎沒有被調用。任何人都可以幫助我完成它並將它重構爲一個可愛的小公用程序宏?
方法定義是全局的,因此在詞彙或動態環境中添加和刪除方法將影響其他線程(假設多處理)。 – 2011-04-27 16:58:24
hmm,shit ......除非......在我的使用案例中,我想專門研究一個特定的實例,因此如果實例被共享,那麼所有線程都將受到影響,這是我想要的,如果不共享,動態方法將不適用。雖然我希望像一個更抽象的「工具般」的包裝...感謝您的鐘聲。 – Paralife 2011-04-27 17:20:01
要全局啓用特定實例的日誌記錄,請考慮使用'change-class'將實例的類更改爲具有執行日誌記錄的'my-meth:around'方法的子類,然後通過更改回原始來禁用日誌記錄類。使用宏來編寫抽象包裝。 – 2011-04-27 17:41:05