开发者

Debugging generic functions in R

开发者 https://www.devze.com 2022-12-10 20:33 出处:网络
How do you debug a generic function (using debug, or mtrace in the debug package)? As an example, I want to debug cenreg in the NADA package, specifically the method that takes a formula input.

How do you debug a generic function (using debug, or mtrace in the debug package)?

As an example, I want to debug cenreg in the NADA package, specifically the method that takes a formula input.

You开发者_StackOverflow社区 can retrieve the method details like this:

library(NADA)
getMethod("cenreg", c("formula", "missing", "missing"))

function (obs, censored, groups, ...) 
{
    .local <- function (obs, censored, groups, dist, conf.int = 0.95, 
        ...) 
    {
        dist = ifelse(missing(dist), "lognormal", dist)

...
}

The problem is that cenreg itself looks like this:

body(cenreg)
# standardGeneric("cenreg")

I don't know how to step through the underlying method, rather than the generic wrapper.


My first two suggestions are pretty basic: (1) wrap your function call in a try() (that frequently provides more information with S4 classes) and (2) call traceback() after the error is thrown (that can sometimes give hints to where the problem is really occuring).

Calling debug() won't help in this scenario, so you need to use trace or browser. From the debug help page:

"In order to debug S4 methods (see Methods), you need to use trace, typically 
calling browser, e.g., as "
  trace("plot", browser, exit=browser, signature = c("track", "missing")) 

S4 classes can be hard to work with; one example of this is the comment in the debug package documentation (regarding the usage of mtrace() with S4 classes):

"I have no plans to write S4 methods, and hope not to have to
debug other people’s!"

A similar question was asked recently on R-Help. The recommendation from Duncan Murdoch:

"You can insert a call to browser() if you want to modify the source.  If
you'd rather not do that, you can use trace() to set a breakpoint in it.
The new setBreakpoint() function in R 2.10.0 will also work, if you
install the package from source with the R_KEEP_PKG_SOURCE=yes
environment variable set.  It allows you to set a breakpoint at a
particular line number in the source code."

I've never done this before myself (and it requires R 2.10.0), but you might try installing from source with R_KEEP_PKG_SOURCE=yes.

Incidentally, you can use the CRAN mirror of NADA in github to browse the source.


For a long time this was a standard annoyance point for S4 method debugging. As pointed out by Charles Plessy, I worked with Michael Lawrence to add a number of features to R that are intended to make this easier.

debug, debugonce, undebug and isdebugged all now take a signature argument suitable for specifying s4 methods. Furthermore, debugging S4 methods this way bypasses the weird implementation detail that you previously had to deal with by hand by browsering into the method via trace, stepping through the .local definition, debugging that, then continuing.

In addition, I added debugcall, which you give an actual, full call that you would want to invoke. Doing so sets debugging on the first closue which will be invoked when evaluating that call that is not an S3 or S4 standard generic. So if you are calling a non-generic, that will just be the top level function being called, but if it is a standard S3 or S4 generic, the first method that will be hit is debugged instead of the generic. A "standard S3 generic" is defined as a function where the first top-level (ignoring curly braces) call in the body is a call to UseMethod.

Note we went back and forth on the design of this but at the end of the day settled on debugcall not actually executing the function call being debugged, but it returns the call expression which you can pass it to eval if desired, as illustrated in ?debugcall.

0

精彩评论

暂无评论...
验证码 换一张
取 消