全局变量和作用域 - R

Global variable and scope - R

我不明白为什么 R 中的全局范围列表不能从函数内部修改,如下所示:

global <<- list()

f <- function(x) {
  global[[x]] <- "blah"
}

f(1)
f(2)
print(global)

输出为

list()

但是,我期待输出:

[[1]]
[1] "blah"

[[2]]
[1] "blah"

这是为什么?我是否也必须将列表的每个元素都声明为全局的?

在函数块外部声明的局部范围变量似乎也是如此。

谢谢!

我相信您只是对 <<- 的实际作用感到有点困惑。来自 help("<<-"):

The operators <<- and ->> are normally only used in functions, and cause a search to made through parent environments for an existing definition of the variable being assigned. If such a variable is found (and its binding is not locked) then its value is redefined, otherwise assignment takes place in the global environment.

所以从这里可以清楚地看出,<<- 不会在 运行 所在的位置创建 "global variable"。事实上,这根本不是 R 的工作原理。

相反,<<- 执行某种 "global assignment",允许您修改当前范围之外的变量。

它是更精确 assign() 的一种粗略版本。通常不鼓励使用这两种工具,因为它们往往会破坏 R 使用的函数式编程范式(即无副作用)。像其他任何东西一样,它们有自己的用途,但通常不用于常规变量处理。

基本上,由于您使用的是“<-”赋值,该函数正在创建 'global' 变量的副本以供在函数范围内使用。

这可以通过添加第二个函数 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