From: Damien Kick
Subject: Re: Stack access--Am I looking for continuations?
Date: 
Message-ID: <0Yfki.6261$zA4.770@newsread3.news.pas.earthlink.net>
Ari Krupnik wrote:
> I'm writing a recursive function, and I find myself asking, how many
> invocations of this function are currently on the stack?  What's the
> value of a local variable 5 invocations down the stack? I could give
> the function an extra argument that contained a list of states the
> function had gone through, but this seems wrong:
> 
> (defun f (args &optional history)
>   ...
>     (setf local-state (make-hash-table))
>     ...
>     (f (cdr args) (cons local-state history))
> 
> 
> Is there a better way to do this in Lisp? Is this something
> continuations do? If there's a resource I should read, I would
> appreciate a pointer.

As with most things, how one goes about doing something probably depends 
on what it is that one wants to do.  For example, I'm guessing that 
something like the following is not really what you're looking for.  Or 
is it?

CL-USER 21 > (defun f (n)
               (when (= n 0)
                 (break))
               (f (1- n)))
F

CL-USER 22 > (f 5)

Break.
   1 (continue) Return from break.
   2 (abort) Return to level 0.
   3 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other 
options

CL-USER 23 : 1 > :b
Interpreted call to F
Interpreted call to F
Interpreted call to F
Interpreted call to F
Interpreted call to F
Interpreted call to F
Call to EVAL
Call to CAPI::CAPI-TOP-LEVEL-FUNCTION
Call to CAPI::INTERACTIVE-PANE-TOP-LOOP
Call to (SUBFUNCTION MP::PROCESS-SG-FUNCTION MP::INITIALIZE-PROCESS-STACK)

CL-USER 24 : 1 > :v
Interpreted call to F:
   N : 0

CL-USER 25 : 1 > :n
Interpreted call to F

CL-USER 26 : 1 > :n
Interpreted call to F

CL-USER 27 : 1 > :n
Interpreted call to F

CL-USER 28 : 1 > :v
Interpreted call to F:
   N : 3

CL-USER 29 : 1 > :c 4
No such restart.
NIL

CL-USER 30 : 1 > :?

:ed      Edit the function associated with the frame
:v       Print the current frame
:bq      Print a quick backtrace of interesting call frames
:b       Print a backtrace down from the current frame
:error   Print the error and how to continue
:n       Go down the stack
:p       Go up the stack
:top     Abort to top level
:a       Abort one level
:c       Continue from error
:ret     Return from frame
:res     Restart frame
:sres    Restart frame, stepping the function
:trap    Cause the debugger to be re-entered on exit from this frame
:<       Go to the top of the stack
:>       Go to the bottom of the stack
:cc      Get the current condition object
:all     Set the debugger options to show all call frames
:l       Print and return the value of a given variable in the current 
frame.
:func    Get the function ovject in the current frame
:bb      Print a full backtrace suitable for a bug report
:lambda  Show the lambda expression for an anonymous interepreted frame
:bug-form <subject> &key <filename>
          Print out a bug report form, optionally to a file.
:get <variable> <command identifier>
          Get a command from the history list and put it in a variable.
:help    Produce this list.
:his &optional <n1> <n2>
          List the command history, optionally the last n1 or range n1 
to n2.
:redo &optional <command identifier>
          Redo a previous command, identified by its number or a substring.
:use <new form> <old form> &optional <command identifier>
          Redo command after replacing old form with new form.
NIL

CL-USER 30 : 1 > :c 3

CL-USER 31 >
From: Damien Kick
Subject: Re: Stack access--Am I looking for continuations?
Date: 
Message-ID: <3eDki.6629$zA4.1723@newsread3.news.pas.earthlink.net>
Ari Krupnik wrote:
> Damien Kick <·····@earthlink.net> writes:
> 
>> Ari Krupnik wrote:
>>> I'm writing a recursive function, and I find myself asking, how many
>>> invocations of this function are currently on the stack?  What's the
>>> value of a local variable 5 invocations down the stack?
>>
>>                                       [...] For example, I'm guessing
>> that something like the following is not really what you're looking
>> for.  Or is it?
>>
>> CL-USER 21 > (defun f (n)
>>               (when (= n 0)
>>                 (break))
>>               (f (1- n)))
>> F
> 
> I was looking for something I could do from inside the function, not
> the REPL. In the example I gave, I can find out how deep the recursion
> is by looking at (length history), for example.

I don't believe that continuations are what you want, either.  It
provides one with a means to "capture the stack" but not the tools to
ask questions about it nor to access a binding at any frame in the
stack.  I think that CLtL2 environments <http://tinyurl.com/2u4h6v>
provide some level of introspection.  Duane Rettig gave a "mega-example"
of using the environment access interface to ask questions about
variable bindings.  I think he has also hinted at the possibility of an
implementation using environment access to implement the debugger but my
google-fu fails me at the moment.  But if you just want to count the 
number of calls to the function, for example, why not just count the 
number of calls to the function?

;; There is probably a more elegant way of doing this...
(defmacro defun-with-count (fn args &body forms)
   (with-gensyms (count)
     ` (defun ,fn ,args
         (let ((,count 0))
           (labels ((,fn ,args
                      (incf ,count)
                      (multiple-value-call #'values
                        (values ((lambda ,args ,@forms) ,@args))
                        ,count)))
             (,fn ,@args))))))

It still seems to me that the "how to capture information" depends on 
what kind of information and what you want to do with it.  Perhaps I'm 
missing something, though.