8

我是 R 新手(通常是编程),并且对为什么以下代码会产生不同的结果感到困惑:

x <- 100

for(i in 1:5){
  x <- x + 1
  print(x)
}

正如我所期望的那样,这将逐步打印序列 101:105。

x <- 100

f <- function(){
  x <- x + 1
  print(x)
}

for(i in 1:5){
  f()
}

但这只会打印 101 五次。

为什么将逻辑打包成一个函数会导致它在每次迭代时恢复为原始值而不是递增?我能做些什么来使它作为一个重复调用的函数工作?

4

2 回答 2

15

问题

这是因为在您的函数中,您正在处理x左侧的局部变量和x右侧的全局变量。您不是x在函数中更新全局,而是将值分配给101本地x。每次调用该函数时,都会发生同样的事情,因此将 local 指定x1015 次,并打印 5 次。

为了帮助可视化:

# this is the "global" scope
x <- 100

f <- function(){
  # Get the "global" x which has value 100,
  # add 1 to it, and store it in a new variable x.
  x <- x + 1
  # The new x has a value of 101
  print(x)
}

这将类似于以下代码:

y <- 100

f <- function(){
  x <- y + 1
  print(x)
}

一种可能的解决方法

至于如何修复它。将变量作为参数,并将其作为更新传回。像这样的东西:

f <- function(old.x) {
    new.x <- old.x + 1
    print(new.x)
    return(new.x)
}

您可能希望存储返回值,因此更新后的代码如下所示:

x <- 100

f <- function(old.x) {
    new.x <- old.x + 1
    print(new.x)
    return(new.x)
}

for (i in 1:5) {
  x <- f(x)
}
于 2013-05-18T14:33:56.803 回答
2

这可以满足您的要求:

f <- function(){
  x <<- x + 1
  print(x)
}

你不应该这样做。全局变量不是一个好的构造。具有副作用的函数会导致代码难以理解和调试。

使用全局的更安全的方法是将其封装到另一个环境中。这是一个例子:

create.f <- function(x) {
  return(function() {
    x <<- x + 1
    print(x)
  })
}

f <- create.f(100)
for (i in 1:5) f()
## [1] 101
## [1] 102
## [1] 103
## [1] 104
## [1] 105

在这里,“全局”x是在定义的主体的环境中create.ff而不是全局环境。函数的环境是定义它的环境(而不是调用它的环境)。

于 2013-05-18T14:42:19.833 回答