Software for Data Analysis: Programming with R (Statistics and Computing)
John Chambers

Ended: Oct. 2, 2013

As soon as we are involved in programming, the situation changes. We now want to specify a debugging action to take when an error occurs. Theaction is specified by the value of the global error option, specified by a call to the options( function as either a function or an unevaluated expression. Once you begin any serious programming, you will benefit from being able to recover information whenever an error occurs. The recommended option during program development is:options(error = recover)If much of your R activity is programming, you may want to have this option specified at session startup, for example by adding it to the .Rprofile file (see ?Startup).
If you don't want to debug interactively at the time of the error, an alternative to recover0 as an error option is options(error=dump.frames), which will save all the data in the calls that were active when an error occurred. Calling the function debugger( later on then produces a similar interaction to recover0. Usually, there is no advantage to dump.frames0, since recoverO behaves like dump.frames() if the computations are not interactive, allowing the use of debugger() later on. Also, some computations don't "save" well, so you may find debugging harder to do later on. For example, interactive graphics and input/output on connections will be easier to study right away, rather than from a dump.
At this point, if you have set options (error=recover), you can proceed to debug in the usual way.The techniques for using traceO can also be adapted to deal with warnings, in case you need to keep running after examining the computations interactively. The simple way is:trace(warning,
Calling traceO adds computations to a specified function, f. In the simplest use, a function is supplied by name to be called, without arguments, at the start of each call to f and/or just before the call returns. The function supplied is usually browser or recover. For example:trace(f1, recover) trace(f2, exit = browser) trace(f3, browser, exit = browser)All future calls to f10 will begin with a call to recoverO; calls to f2() will call browsero on exit, and calls to f30 will call browsero on both entry and exit. These are the quick-and-easy forms of interactive tracing, sufficient for many applications.A second, more powerful use combines traceO with interactive editing of the function. Instead of a fixed change, any modification can be made, and the edited version now, temporarily, takes the place of the original. Thisnot only allows arbitrary debugging code, it provides the most convenient way to experiment with changes in a function from a package.
If you want to change the tracing but start from the current traced version, call traceO with edit=TRUE again. The version you see in the editor will be whatever is current, either with or without tracing. To delete the edits, call untrace(binaryCounts).
The use of tryCatchO can overcome what Bill Venables calls "design infelicities" ; for example, suppose I want to test whether a particular package can be attached, but I only want to test, with no errors or warning messages to confuse my users. The function require0, with its quietly= argument, might appear to do the trick, but it still generates a warning if the package is not available, and an error if the package exists but cannot be loaded (wrong version of R, perhaps). The computation to silently return FALSE in any of these situations is:
For a formal treatment, a more general solution would be to provide a formal mechanism for ensuring that the variable could be treated correctly. A class, say "DataFrameVariable", would encapsulate requirements on classes to be used for variables in a data frame. Methods would be required for coercing from "character" and for selecting a subset of observations (just the - P operator for vectors, but other definitions could be used to allow, for example, matrix variables). The "DataFrameVariable" class would be another class union, defined to include constraints on valid member classes.