22

There's a definitive guide for how to view the source code for a function, but how do you debug a function that's not exported from a package, without manually stepping through the source code that you've found?

library(plm)
> predict.plm
Error: object 'predict.plm' not found
> plm:::predict.plm
function (object, newdata = NULL, ...) 
{
    tt <- terms(object)
    if (is.null(newdata)) {
        result <- fitted(object, ...)
    }
    else {
        Terms <- delete.response(tt)
        m <- model.frame(Terms, newdata)
        X <- model.matrix(Terms, m)
        beta <- coef(object)
        result <- as.numeric(crossprod(beta, t(X)))
    }
    result
}
<environment: namespace:plm>
> debugonce("predict.plm")
Error in debugonce("predict.plm") : could not find function "predict.plm"
> debugonce("plm:::predict.plm")
Error in debugonce("plm:::predict.plm") : 
  could not find function "plm:::predict.plm"
Community
  • 1
  • 1
Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235

3 Answers3

14

It's not at all obvious, but giving the argument as a symbol rather than as a quoted string seems to work fine, i.e.

debugonce(plm:::predict.plm)

rather than

debugonce("plm:::predict.plm")
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • 3
    I'm pretty shocked that `fun="whatever"` actually works in some cases, since `?debug` says `fun` is supposed to be a function. I never would have thought to try setting `fun` to a string. – Joshua Ulrich Mar 02 '14 at 22:28
  • @JoshuaUlrich this has baffled me when I call `do.call`. Passing function is a string feels very unRlike. – Roman Luštrik Mar 25 '14 at 21:52
  • Counter-argument: Passing a function implies that its contents are copied (pass by value), rather than that debug is told where to look and intervene whenever the original function is called. Clearly unquoted is the right way here, but I'm not sure it's more intuitive or R-like. – Ari B. Friedman Mar 28 '14 at 12:26
  • For reference, note the triple colon ```:::```, as compared to double, which will not allow you to access the internal function. – rsmith54 Jul 22 '20 at 19:42
8

One trick I've used is to assign first to a local object:

predict.plm <- plm:::predict.plm

after which you can do fix(), debug(), ... the local copy.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 5
    Depending on the situation (i.e. if the functions are being called from within package functions), I can imagine that one would run into trouble because functions within the package would still see the version in the NAMESPACE first rather than the local copy ... – Ben Bolker Mar 02 '14 at 21:32
  • I wound up solving it doing something similar (copy/pasting into a local object). – Ari B. Friedman Mar 02 '14 at 21:43
  • Yes, I've done it that way too. And often I give it a local prefix, eg `mypredict` to overcome the name clash @BenBolker alluded to. – Dirk Eddelbuettel Mar 02 '14 at 22:02
0

I do this trick: suppose you have to debug the codeline

rmarkdown::render("myDocument.Rmd") 

Then you can add avobe y below the codeline

f <- function () {
  rmarkdown::render("myDocument.Rmd") 
}

Next

debug(f)
f ()
Captain Tyler
  • 500
  • 7
  • 19