【问题标题】:Accessing current environment in R's eval function在 R 的 eval 函数中访问当前环境
【发布时间】:2018-10-02 10:53:30
【问题描述】:

根据this postenvironment()函数是调用当前环境的函数。

但是,我发现至少eval函数不是这样,下面的例子。

.env <- new.env()
.env$info$progress <- 3
.expr <- "environment()$info$progress <- 5"
eval(parse(text = .expr), envir = .env, enclos = .env)

> invalid (NULL) left side of assignment

我也试过assign函数,但也不起作用

.env <- new.env()
.env$info$progress <- 3
.expr <- "assign(info$progress, 11, envir = environment())"
eval(parse(text = .expr), envir = .env, enclos = .env)

> Error in assign(info$progress, 11, envir = environment()) :
> invalid first argument

所以environment 函数未能在eval 中找到当前环境。

如果有人告诉我如何在上述示例中访问当前环境或如何在eval 中解决此问题,我将不胜感激。

【问题讨论】:

  • 您不能通过调用函数并将environment() 作为参数传递来访问函数的当前环境,因为这会将environment() 评估为调用函数的环境(例如ff = function(env) c(env, environment()); ff(environment()) )。你能解释一下你的最终目标吗?可能存在一种方法来构建调用和使用具有适当 R 对象而不是要解析的字符的环境。

标签: r


【解决方案1】:

考虑到不需要调用environment 的事实,可以实现目标(我认为是访问定义的环境)。带有 NULL 参数的函数不会检索任何有用的东西。 .env 对象是一个环境,所以分配应该只是在其中:

.env <- new.env()

.env$info$progres <- 3
.expr <- ".env$info$progres <- 5"
eval(parse(text = .expr) )
#------------
> ls(envir=.env)
[1] "info"
> ?get
> get("info", envir=.env)
$progres
[1] 5

环境赋值操作应该将值放入函数的环境中。我认为当您对未绑定的环境进行分配时,它可能是未定义的。我不会想到environment()$info$progres &lt;- 5 会成功地将值放入.env,因为environment(.)&lt;- 的目标是NULL

回应您的评论:我不确定“a 当前环境”是什么意思。存在“当前环境”并且.env-环境不是那个环境(也不是那个环境,即使是一瞬间)。使用new.env 创建环境不会使其成为当前环境。它只创建一个环境,允许您通过引用其名称在其中存储或检索对象。

 .env <- new.env()
 environment()
#<environment: R_GlobalEnv>

它甚至不在搜索路径上。这是一种等待被引用的“旁观者”。

> search()
 [1] ".GlobalEnv"         "package:acs"        "package:XML"        "package:acepack"    "package:abind"     
 [6] "package:downloader" "package:forcats"    "package:stringr"    "package:dplyr"      "package:purrr"     
[11] "package:readr"      "package:tidyr"      "package:tibble"     "package:tidyverse"  "tools:RGUI"        
[16] "package:grDevices"  "package:utils"      "package:datasets"   "package:graphics"   "package:rms"       
[21] "package:SparseM"    "package:Hmisc"      "package:ggplot2"    "package:Formula"    "package:stats"     
[26] "package:survival"   "package:sos"        "package:brew"       "package:lattice"    "package:methods"   
[31] "Autoloads"          "package:base"      
> ls(envir=.env)
[1] "info"

我发现自己想知道目标是否是使用更面向对象的样式,如果是这样,我建议查看?R6 帮助页面和 R 语言定义中标题为“5 面向对象编程”的部分.

浏览帮助页面查看getAnywhere?find?ls?objects 的代码后,我发现了apropos 的一个特殊用法,您可能会觉得有趣:

apropos("\\.", mode="environment")
[1] ".AutoloadEnv"  ".BaseNamespaceEnv" ".env" ".GenericArgsEnv" ".GlobalEnv" 
[6] ".userHooksEnv" 

如果你使用:

  apropos("." , mode="environment")`

...,尽可能使用最通用的模式构建,您还将找到由 ggplot2-functions 定义的 100 个左右的 ggproto 环境,假设您已加载该包。我认为 Hadley 的“高级编程”可能对这个感兴趣的话题有更多的了解,因为他定义了一个“环境列表”类和函数来操作它们。

【讨论】:

  • 感谢您的回答。然而,这不是它所要求的。在这个答案中,它使用硬编码变量名称“.env”,我问的是关于调用当前环境而不是硬编码名称的任何函数。
【解决方案2】:

environment() 做你认为它做的事。问题在于直接分配给函数调用的结果。

> new.env()$info$progress <- 3
Error in new.env()$info$progress <- 3 : 
  invalid (NULL) left side of assignment
> .env <- new.env()
> .env$info$progress <- 3
> evalq(identical(environment(), .env), envir = .env)
[1] TRUE
> evalq({ e <- environment(); e$info$progress <- 5 }, envir = .env)
> .env$info
$progress
[1] 5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    相关资源
    最近更新 更多