我不明白为什么R中的全局范围列表不能在函数内修改,如下所示:
global <<- list()
f <- function(x) {
global[[x]] <- "blah"
}
f(1)
f(2)
print(global)
输出为
list()
然而,我期待着输出:
[[1]]
[1] "blah"
[[2]]
[1] "blah"
为什么会这样?我是否也必须声明列表中的每个元素都是全局的?
对于在函数块之外声明的局部作用域变量,似乎也是如此。
谢谢!
我相信您只是对<<-
的实际功能有点困惑。来自help("<<-")
:
运算符<lt;-和->>通常仅用于函数中,以及导致在父环境中搜索现有被赋值变量的定义。如果找到这样的变量(并且其绑定未锁定),则重新定义其值,否则作业发生在全球环境中。
因此应该清楚的是,<<-
不会在任何运行位置创建"全局变量"。事实上,R根本不是这样工作的。
相反,<<-
执行一种"全局赋值",允许您修改当前范围之外的变量。
它是更精确的assign()
的一种粗糙版本。通常不鼓励使用这两种工具,因为它们往往会打破R使用的函数式编程范式(即没有副作用)。和其他任何东西一样,它们也有自己的用途,但通常不用于常规变量处理。
基本上,由于您使用的是"<-"赋值,因此函数正在创建"全局"变量的副本,以便在函数的范围内使用。
这可以通过添加第二个函数g()来实现,该函数在"global"在f()中打印出来之前会更改其值,但这次使用的是"<<-"赋值。f()中的第一行为f(x)创建"global"的本地范围副本,然后使用g(x)更新"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)的父对象。在这种情况下,"<<-"指定在f(x)范围内的"global"的值。因此,"global"的全局副本仍然为空,但如果在f()的作用域中打印出"global)",则会得到更新的值。
global <<- list()
f <- function(x) {
global[[x]] <- "blah"
g <- function(x){
global[[x]] <<- "newblah"
}
g(x)
global
}
f(1) #prints 'newblah'
global #empty