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

时间:2019-07-18 00:24:32

标签: r magrittr

我有一个子函数返回一个命名列表,我想使用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

我希望使用list2env的两个environment()调用都应具有相同的结果,但是似乎只有当我将子函数的结果保存到列表中然后传递给它时,进入list2env是我遵守的预期结果。

此外,当我通过.GlobalEnv时,将按预期修改全局环境。

1 个答案:

答案 0 :(得分:1)

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

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

reprex package(v0.3.0)于2019-07-18创建