[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#50834: Feature request: cl-remove-method (prototyped) and buttons fo
From: |
akater |
Subject: |
bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it |
Date: |
Mon, 27 Sep 2021 01:09:00 +0000 |
I don't use CLOS or EIEIO very often but when I do, I remove methods all
the time. I thus think it's a very important part of CLOS worflow.
SLIME inspector (for Common Lisp) offers buttons that remove methods on
the gf's page, e.g.:
Name: PRINT-OBJECT
Arguments: (SB-PCL::OBJECT STREAM)
Method class: #<STANDARD-CLASS COMMON-LISP:STANDARD-METHOD>
Method combination: #<SB-PCL::STANDARD-METHOD-COMBINATION STANDARD ()
{10002158A3}>
Methods:
(TRACE-ENTRY T) [remove method]
(UNREADABLE-RESULT T) [remove method]
(CHANNEL T) [remove method]
(CONNECTION T) [remove method]
...
[remove method] are buttons. Sadly, Elisp doesn't have an inspector but
I've heard of one effort github.com/mmontone/emacs-inspector and anyway,
these buttons would be appropriate in any displayed list of methods,
including the list currently shown in *Help* buffer for the gf.
Example:
Implementations:
[remove] :around (object stream) in ‘cl-print.el’.
Undocumented
[remove] ((object string) stream) in ‘cl-print.el’.
...
Recently it became necessary to use cl-remove-method in a library code
so I tried to write it.
The following seems to work but I'm very far from being confident about
it. Also, methods are cached in lambdas returned by lambdas returned by
cl--generic-get-dispatcher, and I haven't yet figured out a way to get
them out of there; I'm also not sure if they should be removed manually,
or the tables will just get GC'ed given the proposed implementation of
cl-remove-method as is.
>From 50dc42ce1ea504657ccdcf85e9c71a2f27109610 Mon Sep 17 00:00:00 2001
From: akater <nuclearspace@gmail.com>
Date: Sun, 26 Sep 2021 21:33:46 +0000
Subject: [PATCH] Add cl-remove-method
---
lisp/emacs-lisp/cl-generic.el | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 1640975b84..7d5c8ddc0d 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -98,7 +98,7 @@
;; usually be simplified, or even completely skipped.
(eval-when-compile (require 'cl-lib))
-(eval-when-compile (require 'cl-macs)) ;For cl--find-class.
+(eval-when-compile (require 'cl-macs)) ;For cl--find-class, cl-loop
(eval-when-compile (require 'pcase))
(cl-defstruct (cl--generic-generalizer
@@ -1255,6 +1255,35 @@ defun cl--generic-struct-specializers (tag &rest _)
(cl--generic-prefill-dispatchers 0 integer)
(cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
+(cl-defmethod cl-remove-method ((generic-function cl--generic) method)
+ "An equivalent of Common Lisp's method for remove-method
+specialized on
+(COMMON-LISP:STANDARD-GENERIC-FUNCTION COMMON-LISP:METHOD)."
+ (setf (cl--generic-method-table generic-function)
+ ;; delq could cause bugs, let's see if it does
+ (delq method (cl--generic-method-table generic-function)))
+
+ (cl-loop for k being hash-key in cl--generic-combined-method-memoization
+ when (and (eq generic-function (car k))
+ (memq method (cdr k)))
+ do (remhash k cl--generic-combined-method-memoization))
+
+ ;; It might make sense to move this
+ (defalias (cl--generic-name generic-function)
+ (cl--generic-make-function generic-function))
+ ;; to an :after method
+ ;; but it's not even clear to me whether
+ ;; having such :after method would be compatible with Common Lisp standard.
+ generic-function)
+
+(cl-defmethod cl-remove-method ((generic-function symbol) method)
+ "For Common Lisp compatibility in Elisp.
+
+Namely, (cl-remove-method #'f ..) should work correctly but #'f returns symbol
in Elisp."
+ (if-let ((gf (cl--generic generic-function)))
+ (cl-remove-method gf method)
+ (error "No generic function named %s" generic-function)))
+
;;; Dispatch on major mode.
;; Two parts:
--
2.32.0
- bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it,
akater <=