I’m working on an R Package in which I need to manage the state of various objects over time. Conceptually, when the package loads (.onLoad), it checks for the state object in cache and if it doesn’t exist, a new instance is created, saved to cache, and assigned in the global environment. I’ve not been able to see the object in the global environment using .onLoad() after building the site using devtools :: build(). So, I have three questions:
- Is .onLoad() function the right place for this functionality? If so, what is the current best practice for making state variables visible in the global environment?
- Has a solution (package) for managing state across “R sessions” been developed?
- Is there a better conceptual approach to the problem than the one I’ve adopted?
Solutions tried...so far
I’ve scoured SE, read (and re-read) Hadley’s books on R Packages, and Advanced R, brooded over Winston Chang’s vignettes on R6 (links at bottom of post) and I’ve distilled my experiments down to three failed approaches. First, here’s a simple “GameClass” that instantiates a game with three variables, player 1, player 2, and state (of the game).
#' GameClass
#' \code{GameClass} Class that...#'
#' @export
GameClass <- R6::R6Class(
"GameClass",
public = list(
player1 = character(0),
player2 = character(0),
state = character(0),
initialize = function(player1, player2) {
self$player1 <- player1
self$player2 <- player2
self$state <- "1st Match"
}
)
)
Approach 1
Assign the variable to the global environment using the <<- operator
.onLoad <- function(libname, pkgname) {
gameFile <- "./gameFile.Rdata"
if (file.exists(gameFile)) {
game <<- load(gameFile)
} else {
game <<- GameClass$new("Eric", "Cassie")
save(game, file = gameFile)
}
}
Approach 2:
Create a new environment and return it
.onLoad <- function(libname, pkgname) {
gameFile <- "./gameFile.Rdata"
e <- new.env()
if (file.exists(gameFile)) {
e$game <- load(gameFile)
} else {
e$game <- GameClass$new("Eric", "Cassie")
save(e$game, file = gameFile)
}
e
}
Approach 3:
.onLoad <- function(libname, pkgname) {
gameFile <- "./gameFile.Rdata"
if (file.exists(gameFile)) {
game <- load(gameFile)
} else {
game <- GameClass$new("Eric", "Cassie")
save(game, file = gameFile)
}
assign("game", game, envir = .GlobalEnv)
}
Session Info
R version 3.4.1 (2017-06-30)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United
States.1252 LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C LC_TIME=English_United
States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] R6Lab_0.1.0
loaded via a namespace (and not attached):
[1] compiler_3.4.1 R6_2.2.2 tools_3.4.1 yaml_2.1.14
I"m new to OOP, new to R6, this is my first R package and I've been playing around with R for about a year. Clearly, I could benefit from some insight here.
Thanks in advance.
## References ##
[Hadley's Advanced R][1]
[Hadley's R Packages][2]
[Introduction to R6 Classes][3]
[How to define hidden global variables inside R Packages][4]
[Global variables in packages in r][5]
[Global variables in r][6]
[Global variable in a package which approach is more recommended][7]
[1]: http://adv-r.had.co.nz/
[2]: http://r-pkgs.had.co.nz/
[3]: https://cran.r-project.org/web/packages/R6/vignettes/Introduction.html
[4]: https://stackoverflow.com/questions/34254716/how-to-define-hidden-global-variables-inside-r-packages
[5]: https://stackoverflow.com/questions/12598242/global-variables-in-packages-in-r
[6]: https://stackoverflow.com/questions/1236620/global-variables-in-r
[7]: https://stackoverflow.com/questions/28246952/global-variable-in-a-package-which-approach-is-more-recommended