r语言 - 在链式操作 (%>%) 中使用 list2env() 将对象从命名列表分配到函数环境中



我有一个返回命名列表的子函数,我想使用list2env将这些值作为父函数中的对象分配。我遇到的问题是,当我尝试使用 magrittr 管道链接 list2env 时,结果的行为是出乎意料的,并且似乎与我以这种方式将对象分配给全局环境时观察到的行为不一致。我觉得将它们分配给全局环境更危险,因此我想将它们限制在我的父函数环境中。

PS:是的,我知道仅使用命名列表中的对象可能是一个更好的解决方案,但是我问题的更大上下文需要此解决方案:本质上,我遇到一种情况,即我在多个目录上运行一个函数以加载具有多个对象的RData文件在我的父函数环境中。但是,在某些目录中,此文件尚未创建,而是必须使用子函数进行编译,我想通过从目录中的文件构建这些对象,然后将它们分配给父函数环境来模拟加载RData文件的行为。

#setup
rm(list=ls())
require(magrittr)
#make a dummy parent function
parentFx <- function() {
#make a dummy internal function that will return a named list that we want to assign to the parent fx environment
makeList <- function() {
message('making list')
#return objects in a named list (we can assign this to the parent env using list2env)
list('a'=1, 'b'=2, 'c'=3) %>% 
return
}
#build the list and then pass it to list2env using a pipe
makeList() %>% 
list2env(., envir = environment()) 
#check environment for desired changes
message('checking it once')
ls() %in% c('a','b','c') %>% 
any %>% 
print
#build the list and save it
l <- makeList()
#then pass it on to list2env
list2env(l, envir=environment())
#now we see the list has been assigned to the fx environment
message('checking it twice')
ls() %in% c('a','b','c') %>% 
any %>% 
print
#as a final test, we can observe that this behavior does not seem to apply to the global environment
#build the list and then pass it to list2env using a pipe (this time use global)
makeList() %>% 
list2env(., envir = .GlobalEnv) 
}
#run parent function
parentFx()
#check global environment for changes
ls() %in% c('a','b','c') %>% any %>% print

我希望我的两个使用environment()list2env调用应该具有相同的结果,但似乎只有当我将子函数的结果保存到列表中然后将其传递给list2env时,我才会观察到预期的结果。

此外,当我传递.GlobalEnv时,全局环境会按预期修改。

我认为这是因为管道流内部使用了不同的环境。这可以在我创建的简单示例中看到。

library("magrittr")
environment()
#> <environment: R_GlobalEnv>
1 %>% {print(environment())}
#> <environment: 0x0000000009900598>

而且,您的函数在parentFx()中使用"正确"环境时有效。

parentFx <- function() {
env <- environment()
makeList <- function() {
list('a'=1, 'b'=2, 'c'=3)
}
makeList() %>% 
list2env(., envir = environment()) 
message('checking it once')
ls() %in% c('a','b','c') %>% 
any %>% 
print
makeList() %>% 
list2env(., envir = env) 
message('checking it twice')
ls() %in% c('a','b','c') %>% 
any %>% 
print
}
parentFx()
#> checking it once
#> [1] FALSE
#> checking it twice
#> [1] TRUE

创建于 2019-07-18 由 reprex 软件包 (v0.3.0)

最新更新