[R-pkg-devel] Save and restoring random number seed in a package function

Noah Greifer no@h@gre||er @end|ng |rom gm@||@com
Wed Sep 14 16:30:44 CEST 2022


Hello fellow developers,

I am attempting to solve the problem of saving the state of the random
generator so that the state can be recovered in a future call. Essentially,
my function generates random numbers, performs an operation on them (saving
the result), and throws them out (saving them would require too much
memory). A second function is meant to take the output of the first
function, generate the same random numbers, and perform a different
operation on them.

This is exactly what happens in the *boot* package: the boot() function
saves the random seed (extracted from .Random.Seed), and the boot.array()
function extracts the saved seed from the boot() output, sets the seed to
that value, re-generates the same set of random numbers, and then
re-sets the seed to what it was before boot.array() was called. This has
the following benefits: 1) it allows the same random numbers to be drawn;
2) the random numbers don't need to be saved, which is good because they
would take up a lot of memory and boot.array() is an optional function (it
is used in boot.ci() with type = "bca" for those curious); and 3) the seed
carries on from where it left off before boot.array() was called instead of
being set to what it was after boot() was called.

This is implemented in boot in the following way (code abbreviated):

boot <- function(...) {
  seed <- .Random.Seed
  #Random numbers generated
  out <- list(seed = seed
                  #Other stuff is in this list
              )
  out
}

boot.array <- function(boot.out) {
  #Save current random seed in `temp`
  if (exists(".Random.seed", envir = .GlobalEnv, inherits = FALSE))
    temp <- get(".Random.seed", envir = .GlobalEnv, inherits = FALSE)
  else temp <- NULL

  #Assign saved seed from boot.out
  assign(".Random.seed", boot.out$seed, envir = .GlobalEnv)

  #Generate same random numbers from boot() call

  #Restore random seed to what it was before boot.array() call
  if (!is.null(temp))
    assign(".Random.seed", temp, envir = .GlobalEnv)
  else rm(.Random.seed, pos = 1)
}

This seems to work as intended. However, this violates the CRAN policy of
changing the global environment. When I used this exact code in a package I
submitted, the package was rejected for it. The message I received was

> Please do not modify the .GlobalEnv (e.g.: by changing the .Random.seed
> which is part of the global environment). This is not allowed by the CRAN
> policies.


I'm curious what you think the best course of action might be, and what the
current policy means for the *boot* package. Thanks for your help.

Noah

	[[alternative HTML version deleted]]



More information about the R-package-devel mailing list