The following objects are trace-able: closures, [f]subrs, [n]lambdas, macros. To trace, you do (trace name1 name2 ...). This will SETQ name1, name2, ... to traced objects (they have actual datatype traced). To untrace, you do (untrace name1 name2 ...). This will SETQ name1, name2, ... to the functional component of the trace object which the variables were originally set to. Traced objects print as # or #. By default name is used. (trace-print name) or (trace-print definition) can be used to toggle this. (trace-print) tells you what the current mode is. Both the system printer and pretty-printer will respect this setting. Traced functions will do typeout of "Enter name (arg1 arg2 ...)" where arg1, etc have been evaluated already if appropriate (not an nlambda, macro, or fsubr). If the name of the function is available, it is printed. If the function was called through apply, the name will not be available, so the traced-object will print instead -- eg, "Enter # (arg1 arg2 ...)". An arrow will be drawn on the terminal from the entry to the return value. Traced macros will do slightly different thing. "Macro name (name ...)" will appear -- ie, the thing following name will be the whole form. Then arrows will be drawn to the expansion and the result. If you only want to see macro expansions or macro results, the toggle is (trace-macro expansion), (trace-macro return), (trace-macro all). Just doing (trace-macro) will give you information about the current state. Traced macros cannot be applied. Possible later features: (1) Traced functions cannot be closed over; this may get changed later. (2) It is not possible to trace a nameless function. There is no reason you couldn't but I haven't invented a protocol for it yet.