Mon 13 Apr 2026 09:13:51 BST
| package |
version |
| emacs |
GNU Emacs 30.2.50 (build 1, aarch64-apple-darwin25.3.0, Carbon Version 170 AppKit 2685.4) of 2026-03-16 |
| helpful |
20250408.334 (melpa) |
;; Edebug replaces function source code with a sexp that has
;; edebug-enter', edebug-after' etc interleaved. This means the
;; function is interpreted, so `indirect-function' returns a list.
indirect-function was changed 2023 (line 2491).
The result is no longer a list, but an interpreted-function, so (consp (indirect-function sym)) will always return nil.
ELISP> (type-of (indirect-function 'helpful--edebug))
interpreted-function
@Wilfred Is there an alternative that'll allow helpful--edebug-p to function as before?
My version of helpful--edebug-p (uses aref suggestion for interpreted-function objects):
(defun helpful--edebug-p (sym)
"Does function SYM have its definition patched by edebug?"
(when (closurep (indirect-function sym))
(let ((fn-def (aref (indirect-function sym) 1)))
;; Edebug replaces function source code with a sexp that has
;; `edebug-enter', `edebug-after' etc interleaved.
;; `indirect-function' returns an interpreted-function, inpectable with `aref`.
(when (consp fn-def)
(-let [fn-end (-last-item fn-def)]
(and (consp fn-end)
(eq (car fn-end) 'edebug-enter)))))))
Investigation
When edebug is turned on, helpful--edebug-p ((consp fn-def)) always returns nil. This prevents the helpful-edebug-button from being updated to Disable edebug.
I've tested using edebug (both via the helpful-edebug-button and manually) on helpful--edebug (as you'll be familiar with what to expect). I've also included the Symbol Properties (as provided in the helpful page for helpful--edebug).
Results for (indirect-function 'helpful--edebug)
Before turning on edebug
ELISP> (indirect-function 'helpful--edebug)
#<subr helpful--edebug>
After turning on edebug
ELISP> (indirect-function 'helpful--edebug)
#f(lambda (button) [t] "Toggle edebug for the current symbol."
(edebug-enter 'helpful--edebug (list button)
#'(lambda nil :closure-dont-trim-context
(edebug-after (edebug-before 0) 4
(helpful--toggle-edebug
(edebug-after (edebug-before 1) 3
(button-get
(edebug-after 0 2 button)
'symbol))))
(edebug-after (edebug-before 5) 6 (helpful-update)))))
ELISP> (consp (indirect-function 'helpful--edebug))
nil
Symbol properties
Symbol Properties
edebug
(#<marker at 15435 in helpful.el> nil [76 100 118 127 128 131 147]
(#<window 18 on *helpful function: helpful--edebug*> . 15435))
edebug-behavior
edebug
edebug-coverage
[edebug-unknown edebug-unknown edebug-unknown edebug-unknown edebug-unknown
edebug-unknown edebug-unknown]
edebug-freq-count
[0 0 0 0 0 0 0]
function-history
(nil #<subr helpful--edebug>)
ghost-edebug
nil
After turning off edebug
ELISP> (indirect-function 'helpful--edebug)
#f(lambda (button) [t] "Toggle edebug for the current symbol."
(helpful--toggle-edebug (button-get button 'symbol)) (helpful-update))
ELISP> (consp (indirect-function 'helpful--edebug))
nil
Symbol properties
Symbol Properties
edebug
#<marker at 15435 in helpful.el>
edebug-behavior
edebug
edebug-coverage
[edebug-unknown edebug-unknown edebug-unknown edebug-unknown edebug-unknown
edebug-unknown edebug-unknown]
edebug-freq-count
[0 0 0 0 0 0 0]
function-history
("/Users/m/.emacs.d/elpa/helpful-20250408.334/helpful.el"
#[(button)
((edebug-enter 'helpful--edebug (list button)
#'(lambda nil :closure-dont-trim-context
(edebug-after (edebug-before 0) 4
(helpful--toggle-edebug
(edebug-after (edebug-before 1) 3
(button-get
(edebug-after 0 2 button)
'symbol))))
(edebug-after (edebug-before 5) 6 (helpful-update)))))
(t) nil "Toggle edebug for the current symbol."]
nil #<subr helpful--edebug>)
ghost-edebug
(#<marker at 15435 in helpful.el> nil [76 100 118 127 128 131 147]
(#<window 18 on *helpful function: helpful--edebug*> . 15435))
Found the following references for #f() notation:
Ref:
- https://stackoverflow.com/a/72561466
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Special-Read-Syntax.html
- https://github.com/emacs-mirror/emacs/blob/5caab891b4541e2ad41d86472a8b256760092f16/etc/NEWS.30#L2001-L2015
Evaluating a 'lambda' returns an object of type 'interpreted-function'.
Instead of representing interpreted functions as lists that start with
either 'lambda' or 'closure', Emacs now represents them as objects
of their own 'interpreted-function' type, which is very similar
to 'byte-code-function' objects (the argument list, docstring, and
interactive forms are placed in the same slots).
Lists that start with 'lambda' are now used only for non-evaluated
functions (in other words, for source code), but for backward compatibility
reasons, 'functionp' still recognizes them as functions and you can
still call them as before.
Thus code that attempts to "dig" into the internal structure of an
interpreted function's object with the likes of 'car' or 'cdr' will
no longer work and will need to use 'aref' instead to extract its
various subparts (when 'interactive-form', 'documentation', and
'help-function-arglist' aren't adequate).
Mon 13 Apr 2026 09:13:51 BST
indirect-functionwas changed 2023 (line 2491).The result is no longer a
list, but aninterpreted-function, so(consp (indirect-function sym))will always returnnil.@Wilfred Is there an alternative that'll allow
helpful--edebug-pto function as before?My version of
helpful--edebug-p(usesarefsuggestion for interpreted-function objects):Investigation
When
edebugis turned on,helpful--edebug-p((consp fn-def)) always returnsnil. This prevents thehelpful-edebug-buttonfrom being updated toDisable edebug.I've tested using
edebug(both via thehelpful-edebug-buttonand manually) onhelpful--edebug(as you'll be familiar with what to expect). I've also included theSymbol Properties(as provided in the helpful page forhelpful--edebug).Results for
(indirect-function 'helpful--edebug)Before turning on
edebugAfter turning on
edebugSymbol properties
After turning off
edebugSymbol properties
Found the following references for
#f()notation:Ref: