piccolbo
piccolbo

Reputation: 1315

mutable default package values in R

I am developing a package for R and I would like to set some package-wide defaults with the ability to modify them later. I know this sounds like global variables and thus evil, but I need this to control profiling and debugging and to set the backend (the package can use a variety of external program to do its thing and I call them backends).

All these three settings should change at the same time for all the functions in a call stack. For example, if I call mypackage::function1(profiling = T) and function1 calls mypackage::function2 and mypackage::function3 I would like profiling to be on for those too as far as that call is concerned. One solution could be to do mypackage::turn.on.profiling() and have all the function refer to some package variable, but it requires trickery with locked environments and stuff like that.

Another could be dynamic scoping, simulated though the sys.frame family of functions (that is, once profiling is on, it's on for anything below that point on the stack). Don't tell me that profiling in R doesn't work like that because this is a different type of profiling, built on top of the existing one but different.

I have no doubt that I can hack it one way or another, but I was wondering if there is a canonical solution or at least some precedent in CRAN for something of this sort so that I won't reinvent the wheel.

Upvotes: 2

Views: 141

Answers (2)

Tommy
Tommy

Reputation: 40821

Another simple way is to put the parameters in an environment object in your package and have your turn.on.profiling-like function modify it.

# Don't export this 
.profileOptions <- new.env(parent=emptyenv())
.profileOptions$enabled <- FALSE

# export this one
profilingEnabled <- function(flag = NA) {
    oldFlag <- .profileOptions$enabled
    if (!is.na(flag)) {
       .profileOptions$enabled = flag
    }
    oldFlag
}

# then use it
profilingEnabled() # returns TRUE or FALSE
profilingEnabled(TRUE) # enables profiling, returns previous state

Upvotes: 2

Joshua Ulrich
Joshua Ulrich

Reputation: 176658

You could set an option at the beginning of function1 and unset it at the end or via on.exit. Something like:

function1 <- function() {
  op <- options()       # current state of options
  on.exit(options(op))  # restore when function exits
  print(getOption("mypackage.profiling"))
  options(mypackage.profiling=TRUE)  # turn on profiling
  print(getOption("mypackage.profiling"))
}
options(mypackage.profiling=FALSE)
function1()
# [1] FALSE
# [1] TRUE
getOption("mypackage.profiling")
# [1] FALSE

You could also set options during package startup via .onLoad

Upvotes: 3

Related Questions