Hello,
I want to write a generic errorhandler-function. This function should
return the functionname, where the error has happened in a dynamic way.
Is it possible to fetch the functionname from inside a function?
Regards
Michael
Michael H�nisch <················@ascad.de> wrote:
> I want to write a generic errorhandler-function. This function should
> return the functionname, where the error has happened in a dynamic way.
>
> Is it possible to fetch the functionname from inside a function?
you can redefine defun, but I'm not a Lisp expert, there might be
problems with this:
(defparameter *function-backtrace* nil)
(shadow 'defun)
(defmacro defun (name arglist &rest body)
`(cl:defun ,name ,arglist
(push (quote ,name) *function-backtrace*)
(unwind-protect
,@body
(pop *function-backtrace*))))
Then for your functions you can get the backtrace:
CL-USER > (defun test () *function-backtrace*)
TEST
CL-USER > (defun test2 () (test))
TEST2
CL-USER > (test2)
(TEST TEST2)
--
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Frank Buss wrote:
> Michael Hönisch <················@ascad.de> wrote:
> > I want to write a generic errorhandler-function. This function
should
> > return the functionname, where the error has happened in a dynamic
way.
> >
> > Is it possible to fetch the functionname from inside a function?
>
> you can redefine defun, but I'm not a Lisp expert, there might be
> problems with this:
Reminds me of this thread, where lambda list destructuring was
mentioned.
http://groups.google.com/groups?hl=en&lr=&c2coff=1&safe=off&threadm=sfwd6by55if.fsf%40shell01.TheWorld.com&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26safe%3Doff%26c2coff%3D1%26q%3Ddefun%2Bdestructuring%26btnG%3DSearch%26meta%3Dgroup%253Dcomp.lang.lisp.*
&whole would be obviously useful for such uses like the original poster
wants. Maybe we need a metafunction protocol or something.
MfG,
Tayssir
Frank Buss <··@frank-buss.de> writes:
> (push (quote ,name) *function-backtrace*)
> (unwind-protect
> ,@body
> (pop *function-backtrace*))))
I suggest
(let ((*function-backtrace* (cons ',name *function-backtrace*)))
,@body)
as an alternative for this particular fragment.
--
Lars Brinkhoff, Services for Unix, Linux, GCC, HTTP
Brinkhoff Consulting http://www.brinkhoff.se/
Michael H�nisch <················@ascad.de> writes:
> Hello,
>
> I want to write a generic errorhandler-function. This function should
> return the functionname, where the error has happened in a dynamic way.
>
> Is it possible to fetch the functionname from inside a function?
Not portably. Moreover, a lot of functions don't have a name, or have
several names.
However, most implementations provides a way to recover the
backtrace. You could check the sources of slime to see how they do it.
--
__Pascal Bourguignon__ http://www.informatimago.com/
Voting Democrat or Republican is like choosing a cabin in the Titanic.
Michael Hoenisch wrote:
> I want to write a generic errorhandler-function. This
> function should return the functionname, where the error
> has happened in a dynamic way.
I've put a wrapper round defun to record the name
(defmacro defunam (name lambda-list &rest body)
`(defun ,name ,lambda-list
(handler-bind
((error (lambda(condition)
(declare (ignore condition))
(format *debug-io*
"~&Trouble in (~S~{ ~S~})."
',name ;here is the functions name
;; I fail to handle keywords
(list ,@lambda-list)))))
,@body)))
Then we can write functions. When an error is signalled, all
our functions list their names and arguments.
Here is a simple example, which recurses down to zero before
signalling an error due to a failed assertion. The dynamic
path is printed.
(defunam try (n)
(assert (plusp n))
(case (random 2)
(0 (attempt (- n 1)))
(1 (try (- n 1)))))
(defunam attempt (n)
(assert (plusp n))
(case (random 2)
(0 (attempt (- n 1)))
(1 (try (- n 1)))))
* (try 5)
Trouble in (ATTEMPT 0).
Trouble in (TRY 1).
Trouble in (ATTEMPT 2).
Trouble in (TRY 3).
Trouble in (TRY 4).
Trouble in (TRY 5).
Error in function COMMON-LISP::ASSERT-ERROR:
The assertion (PLUSP N) failed.
etc
This has to use handler-bind, not handler-case.
If I had used handler-case, the first matching handler would
have handled the error and that would have been the end of
the matter.
With handler-bind you have to put a non-local exit in the
handler function (such as invoking a restart) in order to
"handle" the condition. If the handler function returns the CL
runtime tries the next one. All my handlers return so each
runs in turn, printing the function name and arguments,
before the CL runtime gets fed up and invokes the debugger.
I hope that gives you some ideas.
Alan Crowe
Edinburgh
Scotland