R中的静态变量

21

我在R中有一个函数,我多次调用它。我想跟踪我已经调用它的次数,并使用它来决定在函数内部要做什么。这是我目前的代码:

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 )
}

我不喜欢在函数之外声明变量count的必要性。在C或C++中,我可以只声明静态变量。在R编程语言中,我能做类似的事情吗?

3个回答

30

以下是一种使用闭包(在编程语言中的意思)的方法,即将计数变量存储在一个仅由您的函数访问的封闭环境中:

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)

6

这里还有另一种方法。这种方法需要输入更少的内容,而且(在我看来)更易读:

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

这个片段以及更复杂的示例可以在这篇R-Bloggers文章中找到。


7
这种方法的缺点是每次运行时实际上都会创建一个 f 的副本。 - hadley
你能解释一下为什么吗?@hadley - hshihab
@hshihab 更改R对象的属性(函数也是R对象)会创建一个副本,因为R具有“写时复制”的行为。也许data.table::setattr函数在这里是一个好选择,因为它通过引用更新属性(而不是复制整个对象)... - R Yoda

2
似乎G. Grothendieck在这里给出了正确的答案:Emulating static variable within R functions 但不知何故,这篇文章在谷歌搜索中的位置更有利,所以我把这个答案复制在这里:
在本地环境中定义f,如下:
f <- local({ 
  static <- 0
  function() { static <<- static + 1; static }
})
f()
## [1] 1
f()
## [1] 2

如何向函数传递参数? - Jeff
@Jeff f <- local({ static <- 0 function(a) { static <<- static + a; static } }) @Jeff f <- local({ static <- 0 function(a) { static << - static + a; static } }) - Обедающий философ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接