在Common Lisp中取消定义类及其所有方法

时间:2013-09-04 16:28:35

标签: common-lisp clos ccl

我想取消定义一个班级及其所有方法,但经过对Googlore的彻底搜索后,我一直无法找到关于如何做到这一点的线索。

我正在使用Commmon Lisp的实现,称为CCL(Clozure CL)。

5 个答案:

答案 0 :(得分:5)

这是一个相当有趣的问题。虽然,sds's answer指出,您可以使用(setf (find-class 'class-name) nil)使(make-instance 'class-name)之类的内容停止工作,但实际上并不会删除该类。例如,您可以将(find-class …)的早期结果保存在其他地方:

CL-USER> (defclass foo () ())
#<STANDARD-CLASS FOO>
CL-USER> (defmethod show ((x foo))
           (print "x is a foo"))
STYLE-WARNING: Implicitly creating new generic function SHOW.
#<STANDARD-METHOD SHOW (FOO) {1002BFD321}>
CL-USER> (defparameter *foo-class* (find-class 'foo))
*FOO-CLASS*
CL-USER> (show (make-instance 'foo))

"x is a foo" 
"x is a foo"
CL-USER> (setf (find-class 'foo) nil)
NIL
CL-USER> (make-instance 'foo)
; Evaluation aborted on #<SIMPLE-ERROR "There is no class named ~ .. {1002FDBC61}>.
CL-USER> (make-instance *foo-class*)
#<#<STANDARD-CLASS FOO> {1003217F91}>

我不确定是否有任何方法可以从系统中删除一个类,并且不清楚它究竟是什么意思,因为它必须解决如何处理任何现有实例的问题该课程。

(setf find-class)也不会删除任何专门用于该类的方法。继续刚开始的例子,因为我们仍然可以在类的实例上调用show,我们仍然可以检索专门的方法:

CL-USER> (show (make-instance *foo-class*))

"x is a foo" 
"x is a foo"
CL-USER> (find-method #'show '() (list *foo-class*))
#<STANDARD-METHOD SHOW ((CLASS #<STANDARD-CLASS FOO>)) {1003A7D081}>

但是,您可以使用REMOVE-METHOD

从通用函数中删除适用的方法
CL-USER> (remove-method #'show (find-method #'show '() (list *foo-class*)))
#<STANDARD-GENERIC-FUNCTION SHOW (0)>
CL-USER> (show (make-instance *foo-class*))
; Evaluation aborted on #<SIMPLE-ERROR "~@<There is no applicable method for the generic function ~2I~_~S~ .. {1002EA5731}>.

在Common Lisp对象系统(CLOS)中,方法不属于类,所以说“[取消定义]类及其所有方法”是没有意义的。相反,CLOS具有泛型函数,程序员定义了专门化泛型函数的方法。如上面的示例所示,虽然可能没有可移植的方法来取消定义类,但您可以删除专门用于该类实例的方法,但您必须追踪它们的内容。有关更多信息,请查看:

本主题也在comp.lang.lisp上进行了讨论:

答案 1 :(得分:2)

只需使用find-class

(setf (find-class 'myclass) nil)

但是,这不会破坏类对象,也不会删除相应的方法。

完整过程需要unintern myclass符号和类的插槽名称 - 但您可能在其他地方使用这些符号,所以要小心!

您还必须从您定义它们的通用函数中remove-method

简而言之,这是一个巨大的企业,当然不值得努力。

只需重新启动Lisp会话。

答案 2 :(得分:2)

这不是便携式的,而是像LispWorks这样的IDE:

  • 使用类浏览器,列出没有继承的类的所有方法,选择方法,从方法菜单调用 undefine

    < / LI>
  • 在编辑器中选择defclass表单,在 definitions 菜单中调用 undefine

CCL IDE可能没有这些命令,但 SLIME + Emacs 可能有类似的东西。

答案 3 :(得分:0)

几个星期前,我发现自己正在删除我正在处理的软件包并重新加载lisp文件以获得相同的预期效果(虽然我同意它有点过分,因为你放弃了所有定义的东西在那个包裹下)。

假设您的类定义位于单独的包中(可能是该包的单独文件),只需切换到cl包然后删除包,重新加载,再次切换回包。一个例子(来自我的sbcl提示符):

TESTPACKAGE> (in-package :cl)
CL> (delete-package :testpackage)
CL> (load "testpackage.lisp")
CL> (in-package :testpackage)
TESTPACKAGE> 

答案 4 :(得分:0)

我偶然发现了这个:

HyperSpec中的标准通用功能#'make-instances-obsolete。 重新定义a时要特别注意它如何与#'defclass相互作用 “标准课”。

还要查看#'fmakunbound#'unintern#'delete-package

(remove-method
  (find-method #'<generic-function-symbol>
               '(:before :after :<some-other-qualifier-you-may-be-interested-in>)
               ;; specializers are the classes or eq specializers
               ;; in method lambda lists
               '(<first-specializer> <second-specializer-and-so-on>)))

最后一段代码接近Joshua Taylor's answer