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

Using list2env() in chained operation (%>%) to assign objects from named list into function environment

我有一个 returns 命名列表的子函数,我想使用 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() 中使用 "correct" 环境时,您的函数可以正常工作。

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

reprex package (v0.3.0)

于 2019-07-18 创建