Static Variables in R
Asked Answered
O

3

22

I have a function in R that I call multiple times. I want to keep track of the number of times that I've called it and use that to make decisions on what to do inside of the function. Here's what I have right now:

f = function( x ) {
   count <<- count + 1
   return( mean(x) )
}

count = 1
numbers = rnorm( n = 100, mean = 0, sd = 1 )
for ( x in seq(1,100) ) {
   mean = f( numbers )
   print( count )
}

I don't like that I have to declare the variable count outside the scope of the function. In C or C++ I could just make a static variable. Can I do a similar thing in the R programming language?

Ostiole answered 6/7, 2009 at 18:48 Comment(0)
C
30

Here's one way by using a closure (in the programming language sense), i.e. store the count variable in an enclosing environment accessible only by your function:

make.f <- function() {
    count <- 0
    f <- function(x) {
        count <<- count + 1
        return( list(mean=mean(x), count=count) )
    }
    return( f )
}

f1 <- make.f()
result <- f1(1:10)
print(result$count, result$mean)
result <- f1(1:10)
print(result$count, result$mean)

f2 <- make.f()
result <- f2(1:10)
print(result$count, result$mean)
result <- f2(1:10)
print(result$count, result$mean)
Calf answered 6/7, 2009 at 19:25 Comment(0)
P
6

Here is another approach. This one requires less typing and (in my opinion) more readable:

f <- function(x) {
    y <- attr(f, "sum")
    if (is.null(y)) {
        y <- 0
    }
    y <- x + y
    attr(f, "sum") <<- y
    return(y)
}

This snippet, as well as more complex example of the concept can by found in this R-Bloggers article

Prosser answered 14/1, 2013 at 17:2 Comment(3)
The downside of this approach is that you're actually creating a copy of f every time you run it.Pardner
Can you please explain why ? @PardnerBirkett
@Birkett Changing an attribute of an R object (and a functions is also an R object) does create a copy due to the "copy on write" behaviour of R. Perhaps the data.table::setattr function would be a good thing here since it updates attributes by reference (not copying the whole object)...Acey
M
3

It seems the right answer was given by G. Grothendieck there: Emulating static variable within R functions But somehow this post got more favorable position in google search, so i copy this answer here:

Define f within a local like this:

f <- local({ 
  static <- 0
  function() { static <<- static + 1; static }
})
f()
## [1] 1
f()
## [1] 2
Moot answered 7/7, 2021 at 15:2 Comment(2)
How do you pass the function a parameter?Neiman
@Neiman f <- local({ static <- 0 function(a) { static <<- static + a; static } })Cantharides

© 2022 - 2024 — McMap. All rights reserved.