[R] Persistent state in a function?

Duncan Murdoch murdoch.duncan at gmail.com
Sat Mar 19 22:57:56 CET 2016


On 19/03/2016 12:45 PM, Boris Steipe wrote:
> Dear all -
>
> I need to have a function maintain a persistent lookup table of results for an expensive calculation, a named vector or hash. I know that I can just keep the table in the global environment. One problem with this approach is that the function should be able to delete/recalculate the table and I don't like side-effects in the global environment. This table really should be private. What I don't know is:
>   -A- how can I keep the table in an environment that is private to the function but persistent for the session?
>   -B- how can I store and reload such table?
>   -C- most importantly: is that the right strategy to initialize and maintain state in a function in the first place?
>
>
> For illustration ...
>
> -----------------------------------
>
> myDist <- function(a, b) {
>      # retrieve or calculate distances
>      if (!exists("Vals")) {
>          Vals <<- numeric() # the lookup table for distance values
>                             # here, created in the global env.
>      }
>      key <- sprintf("X%d.%d", a, b)
>      thisDist <- Vals[key]
>      if (is.na(thisDist)) {          # Hasn't been calculated yet ...
>          cat("Calculating ... ")
>          thisDist <- sqrt(a^2 + b^2) # calculate with some expensive function ...
>          Vals[key] <<- thisDist      # store in global table
>      }
>      return(thisDist)
> }
>
>
> # run this
> set.seed(112358)
>
> for (i in 1:10) {
>      x <- sample(1:3, 2)
>      print(sprintf("d(%d, %d) = %f", x[1], x[2], myDist(x[1], x[2])))
> }


Use local() to create a persistent environment for the function.  For 
example:

f <- local({
   x <- NULL
   function(y) {
     cat("last x was ", x, "\n")
     x <<- y
   }
})

Then:

 > f(3)
last x was
 > f(4)
last x was  3
 > f(12)
last x was  4

Duncan Murdoch



More information about the R-help mailing list