Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefining a class and all its methods in Common Lisp

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

like image 659
Mike2012 Avatar asked Sep 04 '13 16:09

Mike2012


3 Answers

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:

  • Chapter 7. Objects of the HyperSpec and familiarize yourself with some of these concepts, because they do differ from what you find in many languages that are called object oriented. You might find a more gentle introduction in
  • Chapter 16. Object Reorientation: Generic Functions and Chapter 17. Object Reorientation: Classes from Peter Seibel's Practical Common Lisp. The book is a great reference, and the whole thing is available for free online.

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

  • undefining a class
like image 168
Joshua Taylor Avatar answered Nov 05 '22 17:11

Joshua Taylor


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.

like image 22
sds Avatar answered Nov 05 '22 19:11

sds


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.

like image 41
Rainer Joswig Avatar answered Nov 05 '22 19:11

Rainer Joswig