从泛型函数中删除一个方法

Remove one method from a generic function

我已将以下方法添加到通用函数 speak 但现在想在 REPL 中删除此特定方法而不删除通用函数的其余方法。

(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.

函数 remove-methoddocumentation link 没有示例,我不知道引用上面实际 ​​:around 方法的语法是什么。

(remove-method #'speak)
TOO FEW ARGUMENTS

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

来自文档:

remove-method generic-function method

它需要一个通用函数对象和一个方法对象作为参数。

可以通过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>

另请注意,良好的 Lisp 开发环境可能还允许在编辑器或检查器中删除方法。

请注意,在 Lisp 侦听器中,不需要像上面那样调用两次 find-method。变量 * 包含最后一个结果。

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>

这是另一个在 GNU Emacs 中使用 SLIME 的交互示例,并启用了 SLIME 的 演示 功能。 presentation 是 Lisp 输出,它保持打印对象和生成文本之间的联系。

调用find-method函数。它 returns 方法。这里我们使用 presentations,它保持文本和 Lisp 对象之间的联系。输出显示为红色,鼠标敏感。将鼠标移动到红色返回对象上将添加交互选项。

现在键入 (remove-method #'speak,然后在红色输出上单击鼠标中键(或 SLIME 配置使用的任何内容):演示文稿(文本和连接的对象)将被复制到该行。输入 ) 并输入表格。 SLIME 实际上已经构建了一个包含真实对象而不是文本表示的列表,然后。

这就是 repls 在 Symbolics Lisp Machine 和 CLIM / McCLIM 中的工作方式...

如果将 GNU Emacs 与 SLIME 一起使用,您还可以使用 slime-inspector。例如定义泛型函数 foo 和两个方法:

USER> (defgeneric foo (x))
#<STANDARD-GENERIC-FUNCTION FOO (0)>

USER> (defmethod foo ((x string)) (length x))
#<STANDARD-METHOD FOO (STRING) {100B4D7E23}>

USER> (defmethod foo ((x integer)) x)
#<STANDARD-METHOD FOO (INTEGER) {100C355843}>

您有两个主要选项可以进入检查器:

  1. 在 REPL 中,键入 #'foo 以便打印通用方法的表示对象:

    USER> #'foo
    #<STANDARD-GENERIC-FUNCTION FOO (0)>
    

    右键单击 演示文稿(#<...> 内的任意位置)和 select Inspect,或者将光标放在演示文稿中并按 C-c C-v TAB (slime-inspect-presentation-at-point).

  2. 从源文件中,输入 slime-inspect、a.k.a。 C-c I,输入#'foo.

在这两种情况下,您都会看到与此类似的视图:

#<STANDARD-GENERIC-FUNCTION {505A9A2B}>
--------------------
Name: FOO
Arguments: (X)
Method class: #<STANDARD-CLASS COMMON-LISP:STANDARD-METHOD>
Method combination: #<SB-PCL::STANDARD-METHOD-COMBINATION STANDARD () {1000214003}>
Methods: 
(INTEGER) [remove method]
(STRING) [remove method]

(....)

每个 [remove method] 文本实际上是一个按钮,单击或按 Return 可以从通用函数中删除关联的方法。