R语言 如何在环境中放置列表?

vktxenjb  于 2023-03-15  发布在  其他
关注(0)|答案(3)|浏览(129)

我正在开发一个函数,从函数内部获取参数。它按预期工作,但是当我尝试传输结果时,列表中有一个envir。它通过dput输出很好,但是我不能传输它。

> test(iris)
list(envir = <environment>, call = test(iris), fn.info = list(
    fn = "test", dot.keys = NULL, dot.vals = NULL, params = list(
        df = "iris"), map = list(df = "iris"), formals = list(
        df = "--EMPTY--")))

如你所见,INTERNALS获取fn函数名和函数参数。获取的一个元素是envir,它很容易复制如下:

dput( (envir = environment()) );

该列表至少捕获了环境,但当我尝试将其粘贴回会话时,出现错误:

> x = list(envir = <environment>, call = test(iris), fn.info = list(
Error: unexpected '<' in "x = list(envir = <"
>     fn = "test", dot.keys = NULL, dot.vals = NULL, params = list(
Error: unexpected ',' in "    fn = "test","
>         df = "iris"), map = list(df = "iris"), formals = list(
Error: unexpected ')' in "        df = "iris")"
>         df = "--EMPTY--")))
Error: unexpected ')' in "        df = "--EMPTY--")"

理想情况下,我希望有一对函数将其作为字符串在envir之间进行强制转换,这样我就可以传输它。

问题:如何通过dput传输环境?

env.toString(envir) {}

env.fromString(envir) {}

以上是我当前的路线图,但我愿意听取建议。我已经尝试过as.characteras.rawas.hexmode ...我相信deparse在内部可以工作,但如果没有建议的env.fromString,我将无法将环境恢复为对象

kcwpcxri

kcwpcxri1#

正如您所注意到的,dput()不提供重建环境所需的代码

env1 <- new.env()
env1$x <- "something"
env2 <- asNamespace("utils")
env3 <- .GlobalEnv
test <- list(env1, env2, env3, 1, "a") 
dput(test)
#> list(<environment>, <environment>, <environment>, 1, "a")

环境的一个基本属性是它们有一个父环境,所以要复制一个环境,你可能必须复制它的父环境,以及它的父环境的父环境等等。因此,处理一般情况是不可能的(或者是不合理的?)。
然而,有些环境已经在R中有了名称,或者很容易调用,使用asNamespace(),期望dput()做这件事是合理的,但它没有。
{constructive}包可以做到这一点,并且可以通过在列表上使用as.environment(),在更一般的情况下提供“有时足够好”的解决方案。

constructive::construct(test, check = FALSE)
#> list(as.environment(list(x = "something")), asNamespace("utils"), .GlobalEnv, 1, "a")

参数check = FALSE是为了防止它失败,因为通过代码重新创建的对象与输入并不完全相同。
它将很快在CRAN上,但同时:https://github.com/cynkra/constructive
实际上,您可以尝试:

env.toString <- function (envir) {
  sprintf("as.environment(%s)", paste(deparse(as.list(envir)), collapse = "\n"))
}
qvsjd97n

qvsjd97n2#

也许您可以使用ls()来获取环境中所有对象的名称,然后将它们的名称和值放入一个列表中,然后使用list2env() ...从该列表中重构一个环境,类似于:

x <- new.env()
x$foo <- 1:3

xnames <- ls(envir = x)
xlist <- lapply(xnames, function(y) {
  z <- x[[y]]
  if (!inherits(z, 'environment'))
    return(z)
})
names(xlist) <- xnames

dput(list(my_env = xlist))
#> list(my_env = list(foo = 1:3))

a_list <- list(my_env = list(foo = 1:3))

x2 <- list2env(a_list$my_env)
print(x2$foo)
#> [1] 1 2 3
kqlmhetl

kqlmhetl3#

如果您只需要从列表中移除作为环境的项,则只需遍历列表,移除从'environment'继承的元素

x <- list(a = new.env(), b = "foo")
dput(x[-sapply(x, inherits, 'environment')])
#> list(b = "foo")

相关问题