7

For example,

(defun create-function (number)
  `(lambda () (* ,number ,number)))

(defalias 'square-two (create-function 2) "adds two")

(square-two)
Drew
  • 75,699
  • 9
  • 109
  • 225
Russ Kiselev
  • 464
  • 3
  • 10

3 Answers3

6

Edebug does not support instrumenting code constructed at runtime. If you try to instrument create-function, then the stepping will occur when you evaluate (create-function 2), not when you execute square-two.

Edebug does support instrumenting lambda forms though, so you can rewrite your example using lexical binding:

;;; -*- lexical-binding: t -*-
(defun get-lexical-function (number)
  (lambda () (* number number)))

(defalias 'square-two (get-lexical-function 2) "adds two")

Then if you instrument get-lexical-function before evaluating the defalias form, you can step through the lambda when evaluating square-two.

npostavs
  • 9,033
  • 1
  • 21
  • 53
  • "Edebug does not support instrumenting code constructed at runtime." What does that mean? Are you not instrumented code constructed at runtime in your second example? – John DeBord Feb 28 '21 at 20:55
  • No, the code of the closure is already constructed, filling in the lexical binding doesn't make any new code. – npostavs Mar 01 '21 at 13:14
  • I don't understand. I think we are thinking of two different "runtimes" – John DeBord Mar 03 '21 at 05:46
2

Yes.

M-x debug-on-entry RET square-two RET

M-: (square-two) RET

Debugger entered--entering a function:
* square-two()
  eval((square-two) nil)
  eval-expression((square-two) nil nil 127)
  funcall-interactively(eval-expression (square-two) nil nil 127)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)

Use d to step through the function. Use c to skip through a step (skip substeps). And as always, C-h m tells you more about the debugger, including other keys.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • 2
    The question title mentioned `edebug`, not `debug`. – npostavs Nov 26 '17 at 19:46
  • @npostavs: Hopefully someone will post an answer specific to edebug. I don't use edebug, so I can't help there. If edebug cannot be used for such a use case (I tried briefly, but I didn't find a useful solution), an alternative is to use the standard `debug`. But I imagine that edebug can be used for this too. – Drew Nov 27 '17 at 01:43
  • Yes, I'm primarily interested in `edebug`. I've tried using `edebug-on-entry` to little success. – Russ Kiselev Nov 27 '17 at 01:44
1

BTW, while npostavs's solution is the better option for your example, in those cases where you really do need to build the code manually with backquotes (e.g. inside defmacro), you can try:

(defun create-function (number)
  (edebug-\` (lambda () (* ,number ,number))))
Stefan
  • 26,154
  • 3
  • 46
  • 84
  • Hmm, it's interesting, but I can't quite make it work. I get `(invalid-function square-two)`. Changing to `(defmacro create-function (number) (edebug-\` (* ,number ,number)))` produces working code, but I still can't manage to step through it. – npostavs Nov 27 '17 at 10:54
  • Hmm... I guess it's broken somehow, then. I know I've seen it working (back when I bumped into it some years ago while trying to fix something in Edebug), but I've never really made use of it. – Stefan Nov 27 '17 at 14:00