Search code examples
common-lispclos

Remove one method from a generic function


I have added the following method to the generic function speak but would now like to remove this particular method in the REPL without removing the rest of the generic functions' methods.

(defmethod speak :around ((c courtier) string)           ; [1]
  (format t "Does the King believe that ~A?" string)
  (if (eql (read) 'yes)
      (if (next-method-p) (call-next-method))            ; [2]
      (format t "Indeed, it is a preposterous idea.~%"))
  'bow)

[1] The :around method replaces the primary method for the type.
[2] Then it decides whether to call the primary method or not.

The documentation link to the function remove-method has no examples and I don't know what is the syntax to refer to the actual :around method above.

(remove-method #'speak)
TOO FEW ARGUMENTS

(remove-method #'speak :around)
NO-APPLICABLE-METHOD


Solution

  • From the documentation:

    remove-method generic-function method

    It expects a generic function object and a method object as arguments.

    One can find the method via find-method.

    CL-USER 39 > (find-method #'speak
                              (list :around)
                              (list (find-class 'courtier) (find-class t)))
    #<STANDARD-METHOD SPEAK (:AROUND) (COURTIER T) 42001285EB>
    
    CL-USER 40 > (remove-method #'speak
                                (find-method #'speak
                                             (list :around)
                                             (list (find-class 'courtier)
                                             (find-class t))))
    #<STANDARD-GENERIC-FUNCTION SPEAK 422000A68C>
    

    Note also that a good Lisp development environment may also allow to remove methods in the editor or the inspector.

    Note that in the Lisp listener, one does not need to call find-method twice like above. The variable * contains the last result.

    CL-USER 43 > (find-method #'speak
                              (list :around)
                              (list (find-class 'courtier)
                                    (find-class t)))
    #<STANDARD-METHOD SPEAK (:AROUND) (COURTIER T) 4200150DEB>
    
    CL-USER 44 > (remove-method #'speak *)
    #<STANDARD-GENERIC-FUNCTION SPEAK 422000A68C>
    

    Here is another interaction example using SLIME in GNU Emacs with the presentation feature for SLIME enabled. A presentation is Lisp output, which keeps the connection between the printed object and the generated text.

    Slime REPL

    Call the find-method function. It returns the method. Here we use presentations, which keep the connections between text and Lisp objects. The output is displayed in the color red and it is mouse-sensitive. Moving the mouse over the red returned object will add interaction options.

    Now type (remove-method #'speak and then middle-click (or whatever SLIME is configured to use) on the red output: the presentation (the text and the connected object) will be copied to the line. Type ) and enter the form. SLIME has actually constructed a list with the real object and not the textual representation, then.

    This is how repls work on the Symbolics Lisp Machine and in CLIM / McCLIM...