Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listing functions with debug flag set in R

I am trying to find a global counterpart to isdebugged() in R. My scenario is that I have functions that make calls to other functions, all of which I've written, and I am turning debug() on and off for different functions during my debugging. However, I may lose track of which functions are set to be debugged. When I forget and start a loop, I may get a lot more output (nuisance, but not terrible) or I may get no output when some is desired (bad).

My current approach is to use a function similar to the one below, and I can call it with listDebugged(ls()) or list the items in a loaded library (examples below). This could suffice, but it requires that I call it with the list of every function in the workspace or in the packages that are loaded. I can wrap another function that obtains these. It seems like there should be an easier way to just directly "ask" the debug function or to query some obscure part of the environment where it is stashing the list of functions with the debug flag set.

So, a two part question:

  1. Is there a simpler call that exists to query the functions with the debug flag set?
  2. If not, then is there any trickery that I've overlooked? For instance, if a function in one package masks another, I suspect I may return a misleading result.

I realize that there is another method I could try and that is to wrap debug and undebug within functions that also maintain a hidden list of debugged function names. I'm not yet convinced that's a safe thing to do.

UPDATE (8/5/11): I searched SO, and didn't find earlier questions. However, SO's "related questions" list has shown that an earlier question that is similar, though the function in the answer for that question is both more verbose and slower than the function offered by @cbeleites. The older question also doesn't provide any code, while I did. :)

The code:

listDebugged    <- function(items){
    isFunction  <- vector(length = length(items))
    isDebugged  <- vector(length = length(items))

    for(ix in seq_along(items)){
        isFunction[ix]  <- is.function(eval(parse(text = items[ix])))
    }

    for(ix in which(isFunction == 1)){
        isDebugged[ix]  <- isdebugged(eval(parse(text = items[ix])))
    }
    names(isDebugged)   <- items
    return(isDebugged)
}

# Example usage
listDebugged(ls())
library(MASS)
debug(write.matrix)
listDebugged(ls("package:MASS"))
like image 413
Iterator Avatar asked Aug 05 '11 01:08

Iterator


People also ask

How do you debug a function in R?

The function debug() in R allows the user to step through the execution of a function, line by line. At any point, we can print out values of variables or produce a graph of the results within the function. While debugging, we can simply type “c” to continue to the end of the current section of code.

How do you set breakpoints in R?

First you can set an editor breakpoint by clicking to the left of the line number in the source file, or by pressing Shift+F9 with your cursor on the line. A breakpoint is equivalent to a browser() call, but you avoid needing to change your code like browser() .

How do you debug a function?

To debug a function which is defined inside another function, single-step through to the end of its definition, and then call debug on its name. If you want to debug a function not starting at the very beginning, use trace(..., at = *) or setBreakpoint .


3 Answers

Here's my throw at the listDebugged function:

ls.deb  <- function(items = search ()){
  .ls.deb <-  function (i){
    f <- ls (i)
    f <- mget (f, as.environment (i), mode = "function",

               ## return a function that is not debugged
               ifnotfound = list (function (x) function () NULL)
               )

    if (length (f) == 0)
      return (NULL)

    f <- f [sapply (f, isdebugged)]
    f <- names (f)

    ## now check whether the debugged function is masked by a not debugged one
    masked <- !sapply (f, function (f) isdebugged (get (f)))

    ## generate pretty output format:
    ## "package::function"  and "(package::function)" for masked debugged functions
    if (length (f) > 0) {
      if (grepl ('^package:', i)) {
        i <- gsub ('^package:', '', i)
        f <- paste (i, f, sep = "::")
      }

      f [masked] <- paste ("(", f [masked], ")", sep = "")

      f
    } else {
      NULL
    }
  }


  functions <- lapply (items, .ls.deb)
  unlist (functions)
}
  • I chose a different name, as the output format are only the debugged functions (otherwise I easily get thousands of functions)
  • the output has the form package::function (or rather namespace::function but packages will have namespaces pretty soon anyways).
  • if the debugged function is masked, output is "(package::function)"
  • the default is looking throught the whole search path
like image 168
cbeleites unhappy with SX Avatar answered Oct 21 '22 06:10

cbeleites unhappy with SX


This is a simple one-liner using lsf.str:

which(sapply(lsf.str(), isdebugged))

You can change environments within the function, see ?lsf.str for more arguments.

like image 28
sedsiv Avatar answered Oct 21 '22 05:10

sedsiv


Since the original question, I've been looking more and more at Mark Bravington's debug package. If using that package, then check.for.traces() is the appropriate command to list those functions that are being debugged via mtrace.

The debug package is worth a look if one is spending much time with the R debugger and various trace options.

like image 2
Iterator Avatar answered Oct 21 '22 05:10

Iterator