My latest submission to CRAN got bounced back because I have assignments to the global environment which is now frowned upon.
I have an embedded data set (sysdata.rda) that contains configuration parameters based upon state (as in United States) the user resides. I have wanted this embedded data set to be updatable when a new user uses the program. I previously updated this data in the initial function the user uses and made it accessible to the user via global assignment.
I am struggling to figure out how to update this embedded data and make it the default data that the user uses for the remainder of their session.
Previously I housed the data in /data and recently switched it to /R/sysdata.rda as it seemed more suited for that locale. Now I'm not so sure.
Any help greatly appreciated
The key is to do the assignment in an environment other than the global environment. There are two basic techniques, using local()
and <<-
or explicitly creating a new environment:
Working with an explicit environment is straightforward: create the environment and then assign into it like a list:
my_opts <- new.env(parent = emptyenv())
set_state <- function(value) my_opts$state <- value
get_state <- function() my_opts$state
Using local()
is a little more complex, and requires some tricks with <<-
set_state <- NULL
get_state <- NULL
local({
state <- NULL
get_state <<- function() state
set_state <<- function(value) state <<- value
})
For more info on how <<-
works see https://github.com/hadley/devtools/wiki/environments, in the "Assignment: binding names to values" section.
Why not have an foo.R
file in /data
which loads the data and updates it when the user calls data(foo)
? This is one of the allowed options for /data
, but note the following from Writing R Extensions
Note that R code should be “self-sufficient” and not make use of extra functionality provided by the package, so that the data file can also be used without having to load the package.
If you can live with that restriction then data(foo)
could load the data, update it, and ensure that it is in a specific named object, which you then refer to in your functions.