全局变量和作用域 - 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
我不明白为什么 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