Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lisp unroll/partial eval function

Is there a way to show the evaluation steps in Common Lisp like follows:

> (defun fac (n) (if (= n 0) 0 (if (= n 1) 1 (* n (fac (- n 1))))))
FAC
> (step-by-step (fac 3))
0: (FAC 3)
1: (* 3 (FAC 2))
3: (* 3 (* 2 (FAC 1)))
4: (* 3 (* 2 (1)))
5: (* 3 2)
6: 6
Result: 6

Looking for a way to visualize recursion and return values in general for a small course. I know of (step fn) and (optimize (debug 3))) unfortunately this does not produce the desired output, or I don't know how to tell it to.

NOTE: non-emacs/slime solution preferred

like image 823
Rock Avatar asked Dec 12 '25 23:12

Rock


1 Answers

It's not everything you asked for, and the specific output is implementation dependent, but you may get some good milage out of the standard trace. It won't show the expansion like you showed, but it's definitely a way to meet some of your requirements

[to] visualize recursion and return values in general … to see the whole expression on each step. Like having a debug print of each function call.

Many implementations include additional arguments that can customize how things get traced, what gets printed, etc. Here's an example of the default behavior with SBCL:

CL-USER> (defun fac (n) (if (= n 0) 0 (if (= n 1) 1 (* n (fac (- n 1))))))
FAC
CL-USER> (trace fac)
(FAC)
CL-USER> (fac 3)
  0: (FAC 3)
    1: (FAC 2)
      2: (FAC 1)
      2: FAC returned 1
    1: FAC returned 2
  0: FAC returned 6
;=> 6

In CLISP:

CL-USER> (fac 3)
1. Trace: (FAC '3)
2. Trace: (FAC '2)
3. Trace: (FAC '1)
3. Trace: FAC ==> 1
2. Trace: FAC ==> 2
1. Trace: FAC ==> 6
;=> 6
like image 60
Joshua Taylor Avatar answered Dec 15 '25 13:12

Joshua Taylor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!