I have a child function that returns a named list, and I would like to use list2env
to assign those values as objects in my parent function. The issue that I am running into is that when I try to chain list2env using magrittr pipes, the resulting behavior is unexpected and does not seem to line up with the behavior observed when I assign objects to the global environment in this manner. I feel that assigning them to the global environment is more dangerous, so I would like to confine them to my parent function environment.
PS: Yes I understand that it is probably a better solution to just use the objects in the named list but the larger context of my issue requires this solution instead: Essentially I have a situation where I am running a function over multiple directories to load an RData
file with multiple objects in my parent function environment. However, in some directories this file has not been created and instead must be compiled using the child function, which I want to mimic the behavior of loading the RData
file by building those objects from the files in the directory and then assigning them to the parent function environment.
#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
I would expect that both of my list2env
calls that use environment()
should have the same result, yet it seems that only when I save the results of my child function to a list and then pass that into list2env
am I observing the expected result.
Furthermore, when I pass .GlobalEnv
, the global environment is modified as expected.
I think it is because a different environment is used inside the pipe stream. This can be seen in the simple example I created.
library("magrittr")
environment()
#> <environment: R_GlobalEnv>
1 %>% {print(environment())}
#> <environment: 0x0000000009900598>
And, your function works when using the "correct" environment inside your 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
Created on 2019-07-18 by the reprex package (v0.3.0)