qed
qed

Reputation: 23114

Globally turn debug messages on and off in R?

I am thinking of something like this:

> fx = function(x, y) {
+     if (exists("debugging")) {
+         print(x)
+         print(y)
+     }
+     x+y
+ }
> fx(1, 2)
[1] 3
> debugging = 1
> fx(2, 3)
[1] 2
[1] 3
[1] 5

This way you can write as many debugging messages as you want, and when you want to turn them off, you just

rm(debugging)

The problem is the variable debugging (or any name that you give it) can be removed or created by any other package anytime, which is hard to control. Any ideas?

Upvotes: 2

Views: 122

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269714

Use an option. If xyz is the name of your package the debugging code in a typical function would do this:

 if (getOption("xyz.debug", FALSE)) { print(x); print(y) }

Then outside the package issue this to turn on debugging:

 options(xyz.debug = TRUE)

or this to turn it off:

 options(xyz.debug = FALSE) # or options(xyz.debug = NULL)

Its not likely that another package will have an option name prefixed with the name of your package.

The main advantages of this approach are that it does not require any infrastructure other than the if (...) ... statements making it quite lightweight and the overhead for using it in the case that debugging is off is just an if and a call to getOption .

Upvotes: 6

qed
qed

Reputation: 23114

Just for the record, here is what I came up with after reading @G.Grothendieck 's answer:

dbgexec = function(cmd) {
    command = substitute(cmd)
    if(getOption("mypack.debug", FALSE)) eval(cmd, parent.frame())
    invisible(NULL)
}

Example:

> x = 1.1111
> dbgexec({message("value of x: "); print(x)})
value of x:
[1] 1.1111
> options(mypack.debug = FALSE)
> dbgexec({message("value of x: "); print(x)})
# nothing done here

And an experiment with @flodel's answer:

> debugging <- local({
+    stored.value <- FALSE
+    function(bool = NULL)
+       if (is.null(bool)) {
+          stored.value
+       } else {
+          stopifnot(is.logical(bool), length(bool) == 1L)
+          stored.value <<- bool
+       }
+ })
>
>
> dbgexec = function(cmd) {
+     command = substitute(cmd)
+     if(debugging()) eval(cmd, parent.frame())
+     invisible(NULL)
+ }
>
> x = 1; y = 2
> dbgexec({x <- 2; y <- 3; print(x + y)})
> x
[1] 1
> y
[1] 2
> debugging()
[1] FALSE
> debugging(TRUE)
> dbgexec({x <- 2; y <- 3; print(x + y)})
[1] 5
> x
[1] 2
> y
[1] 3

Upvotes: -1

flodel
flodel

Reputation: 89067

Another option would be to define a debugging function in your package:

debugging <- local({
   stored.value <- FALSE
   function(bool = NULL)
      if (is.null(bool)) {
         stored.value
      } else {
         stopifnot(is.logical(bool), length(bool) == 1L)
         stored.value <<- bool
      }
})

# default value:
debugging()
# [1] FALSE

# set value
debugging(TRUE)

# check value
debugging()
# [1] TRUE

This should solve your concern about "What if I decide to change the package name later?" I suppose.

Upvotes: 4

Related Questions