Subject: Re: bug#59820: [PATCH] * nadvice/nadvice.el: support non-symbol (closure/lambda) advices (old Emacs)

From: Stefan Monnier <[email-masked]>
Date: Wed, 11 Oct 2023 02:50:39 -0400

>> Daan, is there a specific use-case that motivates you to want to pass an
>> anonymous lambda to this compatibility library?
>
> I think lambdas are useful for temporary advices that doesn't need to be
> attached to their symbols forever.

That doesn't explain why you need to use them with the forward compatibility
library.

> For example, when pressing "C-<backspace>", or some other editing operations, I
> don't want it to modify the kill ring and the desktop's clipboard.
>
> ```elisp
> (defun my-delete-instead-of-kill-when-interactive-a (func &rest args)
> (if (called-interactively-p 'any)
> (let* ((func (lambda (beg end &rest _) (delete-region beg end))))
> (advice-add #'kill-region :override func)
> (unwind-protect
> (apply func args)
> (advice-remove #'kill-region func)))
> (apply func args)))
> (advice-add #'backward-kill-word :around #'my-delete-instead-of-kill-when-interactive-a)
> (advice-add #'subword-backward-kill :around #'my-delete-instead-of-kill-when-interactive-a)

FWIW, as a general rule I prefer to avoid such transient advice and
prefer to use a permanent advice together with an "enabling" variable:

    (defvar my-dont-kill nil)
    
    (defun my-obey-dont-kill (func beg end &rest args)
      "Obey `my-dont-kill."
      (if my-dont-kill
          (delete-region beg end)
        (apply func beg end args)))
    (advice-add 'kill-region :around #'my-obey-dont-kill)
    
    (defun my-delete-instead-of-kill-when-interactive-a (func &rest args)
      (if (called-interactively-p 'any)
          (let ((my-dont-kill t))
            (apply func args))
        (apply func args)))
    
    (advice-add #'backward-kill-word :around #'my-delete-instead-of-kill-when-interactive-a)
    (advice-add #'subword-backward-kill :around #'my-delete-instead-of-kill-when-interactive-a)

The main advantage, for me, is that `C-h o kill-region` will tell me
that the function has an advice (and I can click on it to jump to its
definition, ...) so I'll be less puzzled when it doesn't behave in "the
normal way".  Sometimes it also comes with the advantage that I can make
the variable buffer-local, contrary to the advice itself.

Of course, in this specific instance, there's another way to get "the
same" result:

    (defun my-delete-instead-of-kill-when-interactive-a (func &rest args)
      (if (called-interactively-p 'any)
          (let ((kill-ring nil)
                (kill-ring-yank-pointer nil)
                (interprogram-cut-function nil))
            (apply func args))
        (apply func args)))
    
    (advice-add #'backward-kill-word :around #'my-delete-instead-of-kill-when-interactive-a)
    (advice-add #'subword-backward-kill :around #'my-delete-instead-of-kill-when-interactive-a)

:-)

        Stefan