3

Within a package I intend to submit to CRAN, I am using .onload(...) to create a new environment in which needed variables will be stored without directly modifying the global environment.

.onLoad <- function(...) {
  envr <- new.env() # when package is loaded, create new environment to store needed variables 
}

This function is saved in a file called zzz.R.

I then use assign(...) to assign variables to the new environment:

assign("x", x, envir = envr)

To retrieve variables in the new environment within my created functions, I do

envr$x

However, on building, installing, loading my package, and running my main function, I receive an error that the object 'envr' cannot be found.

I'm wondering what's happening here.

Creating a new environment directly in R works fine:

envr <- new.env()
envr$a <- 5
envr$a
[1] 5

Any thoughts on resolving the issue?

compbiostats
  • 909
  • 7
  • 22

1 Answers1

2

Your code

envr <- new.env()

assigns the new environment to a local variable in the .onLoad function. When that function exits, the variable isn't visible anywhere else.

You can make your assignment outside the function using <<-, but you have to be careful. That makes R look up through enclosing environments until it finds the variable. If it never finds it, it will do the assignment in the global environment, and that's not yours to write in, so CRAN won't accept your package.

So the right way to do this is to create the variable outside any function as suggested in https://stackoverflow.com/a/12605694/2372064, or to create a variable outside the function but create the environment on loading, e.g.

envr <- NULL
.onLoad <- function(...) {
  envr <<- new.env() # when package is loaded, create new environment to store needed variables 
}
user2554330
  • 37,248
  • 4
  • 43
  • 90
  • Thanks. This helped. One of my functions contains a timer (via proc.time()) which is currently in the user workspace (global environment). I only want the timer to start when this function is called. Putting proc.time() into .onLoad wouldn't make sense. Is there a simple way to accomplish this? – compbiostats Apr 14 '19 at 03:42
  • Yes, use `local()` to create both the function and some persistent storage for it. – user2554330 Apr 14 '19 at 09:28