我在R中编程,我将列表放在列表中。考虑以下向量:
> a = c(1,2,3)
> a
[1] 1 2 3
然后定义一个全局列表:
> foo <<- list()
> foo[[1]] <- a
> foo
[[1]]
[1] 1 2 3
一切都很好。尝试在函数/子例程中修改此列表会导致
> foo <<- list()
> foo
list()
test <- function(){ foo[[1]] <- "a" }
> test()
> foo
list()
我在子程序之外发现foo [[1]]是
> foo[[1]]
Error in foo[[1]] : subscript out of bounds
然而,让我们说我希望foo是全球性的,那么
> foo <<- list()
> foo[[1]] <<- a
Error in foo[[1]] <<- a : object 'foo' not found
给出错误 - 为什么?另外
> foo <<- list()
> foo
list()
test <- function(){ foo[[1]] <<- "a" }
> test()
> foo
list()
> foo[[1]]
Error in foo[[1]] : subscript out of bounds
最后尝试
function(){ foo[[1]] <<-list(); foo[[1]] <<- "a" }
也没有任何结果。我做错了什么?
答案 0 :(得分:3)
你犯了一个可以理解但却很重要的错误:<<-
运算符用于在函数中分配全局环境中的某些东西,而在全局环境中使用它。
要执行您想要执行的操作,请尝试以下操作:
foo <- list()
myfun <- function(){
foo[[1]] <<- 1
}
myfun()
foo
根据@MrFlicks评论编辑:
为了100%正确,<<-
实际上在所有父环境中查找名为foo
的对象。如果找到一个,它会将foo
更改为新值。如果它没有,它就会分配全球环境。通过使用函数assign
,您可以更好地控制分配所在的确切环境,但是使用该函数,您无法设置列表的元素。所以代码将成为:
foo <- list()
myfun <- function(){
tmp <- get('foo',.GlobalEnv)
tmp[[1]] <- 1
assign("foo",tmp, .GlobalEnv)
}
myfun()
foo
不过,这在R中并不是一个好主意。
R没有&#34;全局&#34;与例如Java中的全局变量一样。实际上,R的整个想法违背了全局变量的逻辑。因此,虽然您可能认为<<-
定义了全局,但它所做的只是在全局环境中创建一个空列表。但这不是我们在全局变量下理解的,因为它可以很容易地从全局环境中再次删除:
rm(foo)
myfun()
#> Error in foo[[1]] <<- 1 : object 'foo' not found
除了一些明显的例外,R函数预计没有副作用,因此实际定义全局变量的机制很少。
如果你真的需要一个全局变量,其功能更像是全局变量,你可以做一些不同的事情。 imho最好的想法是使用选项机制。 R允许您定义自己的选项:
options(foo = list())
myfun <- function(){
tmp <- getOption("foo")
tmp[[1]] <- 1
options(foo = tmp)
}
myfun()
getOption("foo")
要删除选项foo
,只需将其设置为NULL
options(foo = NULL)
旁注:如果您正在开发包,您还可以在包的命名空间中定义一个对象,就像使用这些函数一样。但我还没有为这个结构找到一个很好的用例。我的软件包使用选项机制,这是软件包用户期望的内容。