In common lisp: override an existing function within scope? The OP requested something similar. But I want to create a specialized method, not a function. Suppose the method is defined as follows:
defmethod my-meth ((objA classA) (objB classB)) (...)
What I would like to do is (pseudo-code):
(labels ((my-meth ((objA classA) (objB (eql some-object))))) do stuff calling my-meth with the object...)
The real use is that I want to create a temporary environment where setf slot-value-using-class will specialize in eql , essentially creating a specific object on demand, intercepting its record in slots. (The goal is to write down the old and new values ββof the slots somewhere, and then call the next method.) I do not want to create a metaclass, because I can intercept already created instances of standard objects.
Of course, I tried this, and it did not work (because how are you DEFMETHOD in LABELS ?), But I wanted more experienced people to make sure that it was impossible to do this in the same way and / or suggest a suitable way.
Comments?
EDIT:
Daniel and Terrier provide excellent links to expand my knowledge of the possibilities, but I want to push him a little to find a more vanilla approach before heading there. I was exploring the possibility of adding a method upon entering an environment that will specialize in eql and executing the remove method upon exiting. I have not finished yet. If someone played with them, comments would be nice. Will keep the stream up to date.
EDIT 2: I try to do this using the add-method, but there is a problem. Here is what I tried:
(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 (abcd) (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) )))
A call (my-test) with some object slot and data as arguments results in:
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
So, I'm stuck here. Specialization works because applicable methods now include the eql-special: after method, but unfortunately it does not seem to be called. Can anyone help, so I can finish with it and reorganize it into a sweet little utility macro?