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:
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"))
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.
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() .
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 .
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)
}
package::function
(or rather namespace::function
but packages will have namespaces pretty soon anyways). "(package::function)"
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With