Undefining a class and all its methods in Common Lisp

2k views Asked by At

I would like to undefine a class and all of its methods but after a quite thorough search on Googlore I have been unable to find a clue about how to do this.

I am using an implementation of Commmon Lisp called CCL (Clozure CL).

4

There are 4 answers

0
Joshua Taylor On

This is a rather interesting question. Although, as sds's answer points out, you can use (setf (find-class 'class-name) nil) to make things like (make-instance 'class-name) stop working, that doesn't actually delete the class. You could, for instance, save the earlier result of (find-class …) somewhere else:

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}>

I'm not sure whether there's actually any way to delete a class from the system, and it's not clear exactly what it would mean to do so, since it would have to address the issue of what to do with any existing instances of the class.

(setf find-class) also doesn't delete any methods that have been specialized for the class. Continuing the example just started, as we can still call show on instances of the class, and we can still retrieve the specialized methods:

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}>

However, you can remove applicable methods from a generic function using 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}>.

In the Common Lisp Object System (CLOS), methods don't belong to classes, so it doesn't make sense to speak of "[undefining] a class and all of its methods." Rather, CLOS has generic functions, and the programmer defines methods that specialize the generic function. As the above examples show, while there may not be a portable way to undefine a class, you can remove the methods that are specialized for instances of that class, but you'll have to track down what they are. For more information, have a look at:

This topic has also been discussed on comp.lang.lisp:

2
Rainer Joswig On

This is not portable, but in an IDE like LispWorks:

  • use the class browser, list all methods for the class without inherited ones, select the methods, from the methods menu call undefine

  • in the editor select the defclass form, in the definitions menu call undefine

The CCL IDE might not have these commands, but SLIME + Emacs might have something similar.

1
sds On

Just use find-class:

(setf (find-class 'myclass) nil)

However, this will not destroy the class object, nor will it remove the corresponding methods.

The full process would require uninterning the myclass symbol and the slot names of the class - but you might be using those symbols elsewhere, so be careful!

You will also have to remove-method from the generic functions for which you defined them.

In short, this is a huge enterprise, certainly not worth the effort.

Just restart your Lisp session.

0
fobarrrrrrrrrrrrrrrrrrrrrrr On

I just stumbled across this:

Standard Generic Function #'make-instances-obsolete in the HyperSpec. Take special note of how it interacts with #'defclass upon redefining a "standard class".

Also look at #'fmakunbound, #'unintern, #'delete-package and

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

where this last piece of code is close to Joshua Taylor's answer.