我是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次。
为什么将逻辑打包到函数中会导致它在每次迭代时恢复为原始值而不是递增?我能做些什么来使这项工作成为一个反复调用的函数?
答案 0 :(得分:15)
这是因为在你的函数中,你在左侧处理局部变量x
,在右侧处理全局变量x
。您没有更新函数中的全局x
,而是将101
的值分配给本地x
。每次调用该函数时,都会发生相同的事情,因此您将本地x
指定为101
5次,然后将其打印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)
}
答案 1 :(得分: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.f
正文的环境中,其中定义了f
,而不是全局环境。函数的环境是定义它的环境(而不是它被调用的环境)。