unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it
@ 2021-09-27  1:09 akater
  2021-09-27 14:44 ` akater
  0 siblings, 1 reply; 6+ messages in thread
From: akater @ 2021-09-27  1:09 UTC (permalink / raw)
  To: 50834

[-- Attachment #1: Type: text/plain, Size: 1543 bytes --]

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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Add cl-remove-method --]
[-- Type: text/x-diff, Size: 2363 bytes --]

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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it
  2021-09-27  1:09 bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it akater
@ 2021-09-27 14:44 ` akater
  2022-09-02 10:56   ` Lars Ingebrigtsen
  0 siblings, 1 reply; 6+ messages in thread
From: akater @ 2021-09-27 14:44 UTC (permalink / raw)
  To: 50834


[-- Attachment #1.1: Type: text/plain, Size: 121 bytes --]

Various fixes to the prototype patch:
- require subr-x
- more specific default signature
- more extensive documentation


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 865 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Add cl-remove-method --]
[-- Type: text/x-diff, Size: 3330 bytes --]

From decd4e0ed24553981f9b87f59308a10ccdd1c5b6 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 | 56 ++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 1640975b84..c1ef3af3c7 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -98,8 +98,9 @@
 ;; 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))
+(eval-when-compile (require 'subr-x))   ;if-let
 
 (cl-defstruct (cl--generic-generalizer
                (:constructor nil)
@@ -1255,6 +1256,59 @@ defun cl--generic-struct-specializers (tag &rest _)
 (cl--generic-prefill-dispatchers 0 integer)
 (cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
 
+(cl-defgeneric cl-remove-method (generic-function method)
+  "Remove METHOD from GENERIC-FUNCTION by modifying the
+GENERIC-FUNCTION (if necessary).
+
+`cl-remove-method' does not signal an error if METHOD is not one
+of the methods on the GENERIC-FUNCTION.")
+
+(cl-defmethod cl-remove-method ((generic-function cl--generic)
+                                (method cl--generic-method))
+  "An equivalent of Common Lisp's default method for remove-method.
+
+Compatibility note:
+The Common Lisp HyperSpec page on remove-method says
+in Arguments and Values:
+  > method---a method
+and Exceptional Situations: none.
+So then, according to
+1.4.4.3 The ``Arguments and Values'' Section of a Dictionary Entry
+http://www.lispworks.com/reference/HyperSpec/Body/01_ddc.htm
+
+the consequences are undefined if the second value is not a method.
+
+In cl-generic, `cl-remove-method' is not applicable to
+non-methods by default."
+  ;; Credit for compatibility note goes to
+  ;; beach from #commonlisp at libera.chat
+  (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 cl--generic-method))
+  "For Common Lisp compatibility in Elisp.
+
+Namely, (cl-remove-method #'f ..) should work correctly but #'f
+returns symbol in Elisp, hence this method."
+  (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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it
  2021-09-27 14:44 ` akater
@ 2022-09-02 10:56   ` Lars Ingebrigtsen
  2022-09-02 13:29     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 6+ messages in thread
From: Lars Ingebrigtsen @ 2022-09-02 10:56 UTC (permalink / raw)
  To: akater; +Cc: Stefan Monnier, 50834

akater <nuclearspace@gmail.com> writes:

> +(cl-defgeneric cl-remove-method (generic-function method)
> +  "Remove METHOD from GENERIC-FUNCTION by modifying the
> +GENERIC-FUNCTION (if necessary).

I think this sounds very useful -- I don't think we have any other ways
to remove a method, and that's something that I've been missing
sometimes when implementing stuff.

Perhaps Stefan has some comments here; added to the CCs.






^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it
  2022-09-02 10:56   ` Lars Ingebrigtsen
@ 2022-09-02 13:29     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2022-10-04 12:19       ` Lars Ingebrigtsen
  0 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-09-02 13:29 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: akater, 50834

Lars Ingebrigtsen [2022-09-02 12:56:05] wrote:
> akater <nuclearspace@gmail.com> writes:
>> +(cl-defgeneric cl-remove-method (generic-function method)
>> +  "Remove METHOD from GENERIC-FUNCTION by modifying the
>> +GENERIC-FUNCTION (if necessary).
> I think this sounds very useful -- I don't think we have any other ways
> to remove a method, and that's something that I've been missing
> sometimes when implementing stuff.

I'd challenge your use of "very", but I agree it's missing.

> Perhaps Stefan has some comments here; added to the CCs.

Not much to say, except:

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

I don't see why we'd need this.

This is a cache that tries to speed up the construction of combined
methods, whereas in `cl-remove-method` we should only need to flush the
cache that maps tags to their corresponding combined methods and this is
done implicitly by `cl--generic-make-function` (which returns a new
function with a branch new fresh cache).


        Stefan






^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it
  2022-09-02 13:29     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-04 12:19       ` Lars Ingebrigtsen
  2023-09-03  8:38         ` Stefan Kangas
  0 siblings, 1 reply; 6+ messages in thread
From: Lars Ingebrigtsen @ 2022-10-04 12:19 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: akater, 50834

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Not much to say, except:
>
>> +  (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))
>
> I don't see why we'd need this.
>
> This is a cache that tries to speed up the construction of combined
> methods, whereas in `cl-remove-method` we should only need to flush the
> cache that maps tags to their corresponding combined methods and this is
> done implicitly by `cl--generic-make-function` (which returns a new
> function with a branch new fresh cache).

Akater, do you have any comments (or an amended patch)?





^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it
  2022-10-04 12:19       ` Lars Ingebrigtsen
@ 2023-09-03  8:38         ` Stefan Kangas
  0 siblings, 0 replies; 6+ messages in thread
From: Stefan Kangas @ 2023-09-03  8:38 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 50834-done, Stefan Monnier, akater

Lars Ingebrigtsen <larsi@gnus.org> writes:

> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>> Not much to say, except:
>>
>>> +  (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))
>>
>> I don't see why we'd need this.
>>
>> This is a cache that tries to speed up the construction of combined
>> methods, whereas in `cl-remove-method` we should only need to flush the
>> cache that maps tags to their corresponding combined methods and this is
>> done implicitly by `cl--generic-make-function` (which returns a new
>> function with a branch new fresh cache).
>
> Akater, do you have any comments (or an amended patch)?

More information was requested, but none was given within 10 months, so
I'm closing this bug.  If this is still an issue, please reply to this
email (use "Reply to all" in your email client) and we can reopen the
bug report.





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-09-03  8:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-27  1:09 bug#50834: Feature request: cl-remove-method (prototyped) and buttons for it akater
2021-09-27 14:44 ` akater
2022-09-02 10:56   ` Lars Ingebrigtsen
2022-09-02 13:29     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-04 12:19       ` Lars Ingebrigtsen
2023-09-03  8:38         ` Stefan Kangas

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).