Emulating static variable within R functions
Asked Answered
B

2

6

I am looking for ways to emulate 'static' variables within R functions. (I know R is not a compiled language... hence the quotes.) With 'static' I mean that the 'static' variable should be persistent, associated to and modifiable from within the function.

My main idea is to use the attr function:

# f.r

f <- function() {
  # Initialize static variable.
  if (is.null(attr(f, 'static'))) attr(f, 'static') <<- 0L

  # Use and/or modify the static variable...
  attr(f, 'static') <<- attr(f, 'static') + 1L

  # return something...
  NULL
}

This works well, as long as attr can find f. In some scenario's this is no longer the case. E.g.:

sys.source('f.r', envir = (e <- new.env()))
environment(e$f) <- .GlobalEnv
e$f() # Error in e$f() : object 'f' not found

Ideally I would use attr on the 'pointer' of f from within f. sys.function() and sys.call() come to mind, but I do not know how to use these functions with attr.

Anyone ideas or better design patterns on how to emulate 'static' variables within R functions?

Beckon answered 1/12, 2019 at 14:16 Comment(0)
C
6

Define f within a local like this:

f <- local({ 
  static <- 0
  function() { static <<- static + 1; static }
})
f()
## [1] 1
f()
## [1] 2
Corrugate answered 1/12, 2019 at 14:43 Comment(1)
A functor pattern. So obvious. You are the best!Beckon
A
0
rm(list=ls())`
cat("\014")  # ctrl+L`

# Function factory to produce a constant enclosing environment
f2 <- function() {
  # static / persistent list
  glbs <- list()
  glbs[["myvar"]] <- 0

  # function to be returned 
  function(vname = NULL, vvalue = NULL) {
    
    if(is.null(vvalue)){
      
      if(is.null(vname)){
        # print the list 
        print(glbs)
      }else{
        #  get value of vname variable from the list
        return(glbs[[vname]])  
      }
    } else {
      # update  value of vname
      glbs[[vname]] <<- vvalue
      return(vvalue)
    }
  }
  
}

> g2 <- f2()
> g2()
$myvar
[1] 0
> g2("myvar")
[1] 0
> g2("myvar", 1)
[1] 1
> g2()
$myvar
[1] 1

By modifying the internal function any necessary logic of working with static variable(s) could be introduced

Aesthesia answered 14/12, 2022 at 16:10 Comment(1)
This is exactly the same as the accepted answer. Why doublepost?Beckon

© 2022 - 2024 — McMap. All rights reserved.