R中的全局变量和列表赋值,得到意外结果

时间:2017-03-30 14:37:09

标签: r list

我在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" }

也没有任何结果。我做错了什么?

1 个答案:

答案 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中的全局变量不是全局变量

R没有&#34;全局&#34;与例如Java中的全局变量一样。实际上,R的整个想法违背了全局变量的逻辑。因此,虽然您可能认为<<-定义了全局,但它所做的只是在全局环境中创建一个空列表。但这不是我们在全局变量下理解的,因为它可以很容易地从全局环境中再次删除:

rm(foo)
myfun()
#> Error in foo[[1]] <<- 1 : object 'foo' not found

除了一些明显的例外,R函数预计没有副作用,因此实际定义全局变量的机制很少。

如何在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)

旁注:如果您正在开发包,您还可以在包的命名空间中定义一个对象,就像使用这些函数一样。但我还没有为这个结构找到一个很好的用例。我的软件包使用选项机制,这是软件包用户期望的内容。