【问题标题】:Global variable and scope - R全局变量和范围 - R
【发布时间】:2015-04-24 14:22:28
【问题描述】:
我不明白为什么 R 中的全局范围列表不能在函数内进行如下修改:
global <<- list()
f <- function(x) {
global[[x]] <- "blah"
}
f(1)
f(2)
print(global)
输出是
list()
但是,我期待输出:
[[1]]
[1] "blah"
[[2]]
[1] "blah"
这是为什么?我是否必须将列表的每个元素也声明为全局元素?
对于在函数块之外声明的局部范围变量似乎也是如此。
谢谢!
【问题讨论】:
标签:
r
function
scope
global-variables
【解决方案1】:
我相信您对<<- 的实际作用感到有些困惑。来自help("<<-"):
> 运算符通常只用在函数中,并且
导致通过父环境搜索现有的
被赋值的变量的定义。如果找到这样的变量
(并且它的绑定没有被锁定)然后它的值被重新定义,否则
分配发生在全局环境中。
因此应该很清楚,<<- 在任何地方运行时都不会创建“全局变量”。事实上,这根本不是 R 的工作原理。
相反,<<- 执行一种“全局赋值”,允许您修改当前范围之外的变量。
它是更精确的assign() 的一种粗略版本。通常不鼓励使用这两种工具,因为它们往往会破坏 R 使用的函数式编程范式(即没有副作用)。与其他任何东西一样,它们有其用途,但通常不适用于常规变量处理。
【解决方案2】:
基本上,由于您使用的是“
这可以通过添加第二个函数 g() 来看到,它会在 f() 中打印出之前更改“global”的值,但这次使用“
global <<- list()
f <- function(x) {
global[[x]] <- "blah"
g(x)
global
}
g <- function(x){
global[[x]] <<- "newblah"
}
f(1) #prints 'blah', despite the fact the g(x) has already updated the value
global #prints 'newblah'
如果 f(x) 仍然引用“global”的全局副本,它将打印在 g(x) 中分配的“newblah”。相反,它将 f(x) 中分配的值打印到 'global' 的本地范围副本。
但是,在任何函数之外打印 'global' 表明 g(x) 实际上确实更新了 'global' 的全局副本的值。
现在,如果将 g(x) 移动到 f(x) 中,则 f(x) 现在是 g(x) 的父级。在这种情况下,“
global <<- list()
f <- function(x) {
global[[x]] <- "blah"
g <- function(x){
global[[x]] <<- "newblah"
}
g(x)
global
}
f(1) #prints 'newblah'
global #empty