Backtrace

The backtrace feature of uLisp allows you to see the sequence of calls that occurred before an error. This can help you to locate the source of the error in your program.

Backtrace was added to uLisp in Release 4.7.

Example

The following example illustrates the use of backtrace. Consider the following three functions that call each other:

(defun calculate (x) (increment x))

(defun increment (x) (1+ (reciprocal x)))

(defun reciprocal (x) (/ 1 x))

Without backtrace enabled, calling calculate with an argument of 0 gives this error:

> (calculate 0)
Error: '/' division by zero

Here it's not clear where the calculation occurred that caused the error.

Enabling backtrace with:

(backtrace t)

and running the program again gives:

> (calculate 0)
Error [reciprocal <- increment <- calculate]: '/' division by zero

This shows that the error occurred in the function reciprocal, which was called by increment, which in turn was called by calculate.

The backtrace shows up to the last seven calls made before the error.

Enabling backtrace

The backtrace is disabled by default; to enable it:

(backtrace t)

or to disable it again:

(backtrace nil)

You might want to disable it if your program takes advantage of tail-call optimisation, because tail-call optimisation is incompatible with the backtrace feature.

You can see the current state of backtrace by calling the function with no argument; for example:

> (backtrace)
t

Anonymous functions

If an error occurs within an anonymous lambda function, such as:

(defun anon (x) ((lambda (i) (expt i -0.5)) x))

the function will be shown as lambda. For example:

> (anon -1)
Error [lambda <- anon]: 'expt' invalid result

Break

The backtrace can also be displayed from within the break function. For more information see Inserting breaks.