Question about call-next-method
"Edward Kiser (as edkiser at gmail dot com)" <[email protected]>
| Newsgroups | gmane.lisp.lispworks.general |
|---|---|
| Message-ID | <CACzs4FhwSF0QKJo6WGVeKWKoD3FyY0VUHHPxZ2iO663OaC4azQ@mail.gmail.com> |
Hello, Can call-next-method be safely captured in a lambda and returned, to be replayed later? Will it retain the meaning it had when it was captured? My testing in LispWorks suggests that it can be, but I want to know if I can always expect that to be the case or if I am accidentally relying on undefined behavior. The Common Lisp HyperSpec says, "The function call-next-method has lexical scope and indefinite extent, and can only be used within the body of a method defined by a method-defining form." There are various ways to interpret this. For example, it's possible that call-next-method is a global function with indefinite extent but that its meaning varies depending on which method is currently running, and if no method is running, it has no meaning. This would mean that if you wrote a method (call it "A") that returned (lambda () (call-next-method)), or even just #'call-next-method, and later called that procedure when no method was running, it would fail -- and if you called it inside method "B" it would call B's next method instead of A's. When it says "can only be used within the body," does that mean lexically within the body, or dynamically when the body is running, or both? I am sort of hoping that (lambda () (call-next-method)) would capture whatever meaning call-next-method had when "lambda" created the function, and use that same meaning whenever the function was called. An implementation could ensure this by using symbol-macrolet internally to define a different meaning for call-next-method for each method, because call-next-method would be replaced by the macro expander with whatever meaning it is supposed to have in that lexical environment. (The AMOP book uses an "add-function-bindings" function which apparently adds the bindings to the lexical environment, but it doesn't say how "add-function-bindings" works.) The reason I want to save the meaning of call-next-method and use it later is because I am doing continuation-passing-style with a trampoline, and I wanted to use the long form of define-method-combination to combine methods, and each method might want to bounce off the trampoline several times. Also I am using "amb" and I would like it if I could use the saved lambdas more than once. Sincerely, Ed Kiser ---- Experiment: CL-USER 1 > (defclass jikken1 () ()) #<STANDARD-CLASS JIKKEN1 40202ABAB3> CL-USER 2 > (defclass jikken2 () ()) #<STANDARD-CLASS JIKKEN2 40202AE86B> CL-USER 3 > (defgeneric try-something (j)) #<STANDARD-GENERIC-FUNCTION TRY-SOMETHING 4030031B24> CL-USER 4 > (defmethod try-something ((j jikken1)) (format t "Hello 1 ~s!~%" j)) #<STANDARD-METHOD TRY-SOMETHING NIL (JIKKEN1) 402037294B> CL-USER 5 > (defmethod try-something :around ((j jikken1)) (lambda () (call-next-method))) #<STANDARD-METHOD TRY-SOMETHING (:AROUND) (JIKKEN1) 4020374B93> CL-USER 6 > (defmethod try-something ((j jikken2)) (format t "Hello 2 ~s!~%" j)) #<STANDARD-METHOD TRY-SOMETHING NIL (JIKKEN2) 4020375A4B> CL-USER 7 > (defmethod try-something :around ((j jikken2)) (lambda () (call-next-method))) #<STANDARD-METHOD TRY-SOMETHING (:AROUND) (JIKKEN2) 40203768FB> CL-USER 8 > (setq aa1 (try-something (make-instance 'jikken1))) #<anonymous interpreted function 4030000ABC> CL-USER 9 > (setq aa2 (try-something (make-instance 'jikken2))) #<anonymous interpreted function 4030000D1C> CL-USER 10 > (funcall aa1) Hello 1 #<JIKKEN1 4020019FA3>! NIL CL-USER 11 > (funcall aa2) Hello 2 #<JIKKEN2 402001DFC3>! NIL CL-USER 12 > (funcall aa1) Hello 1 #<JIKKEN1 4020019FA3>! NIL _______________________________________________ Lisp Hug - the mailing list for LispWorks users [email protected] http://www.lispworks.com/support/lisp-hug.html