bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#61179: lambda inside interactive form of around advice isn't a closu


From: Jonas Bernoulli
Subject: bug#61179: lambda inside interactive form of around advice isn't a closure
Date: Mon, 30 Jan 2023 16:48:13 +0100

A function used as an around advice may advise the advised function's
interactive form, using (interactive (lambda (spec) ...)).

Unfortunately this inner lambda expression is not turned into a closure
as demonstrated by this simple example:

  ;; -*- lexical-binding: t -*-
  (let ((var :value))
    (lambda (fn &rest args)
      (interactive
       (lambda (spec)
         (message "interactive: %s" var)
         (advice-eval-interactive-spec spec)))
      (message "body: %s" var)
      (apply fn args)))

Or if you want to observe the failure when trying to use such an advice:

  (defun -make-advice ()
    (let ((var :value))
      (lambda (fn &rest args)
        (interactive
         (lambda (spec)
           (message "interactive: %s" var)
           (advice-eval-interactive-spec spec)))
        (message "body: %s" var)
        (apply fn args))))

  (defun -command (arg)
    (interactive (list (read-string ": "))))
  (advice-add '-command :around (-make-advice) '((name . "-advice")))

Could this be changed in the next Emacs release?  Even if this should
make it into 29.1 (which I doubt), it would still be very useful for me
if this could somehow be rewritten to also work in older Emacs releases.
I have tried throwing an eval or two in there, but with limited success.

This gives me an inner closure, but the outside closure does not capture
the same environment it seems:

  (let ((var :value))
    (eval `(lambda (fn &rest args)
             (interactive
              ,(lambda (spec)
                 (message "interactive: %s" var)
                 (advice-eval-interactive-spec spec)))
             (message "body: %s" var)
             (apply fn args))
          t))

I got desperate and also tried things like:

  (call-interactively
   (let ((lex '((var . :value))))
     (eval `(lambda ()
              (interactive
               ,(eval '(lambda (spec)
                        (message "interactive: %s" var)
                        nil)
                      lex))
              (message "body: %s" var))
           lex)))

Thanks for your help!
Jonas





reply via email to

[Prev in Thread] Current Thread [Next in Thread]