【问题标题】:How to access .data environment from code evaluated by eval_tidy如何从 eval_tidy 评估的代码中访问 .data 环境
【发布时间】:2018-08-13 19:18:23
【问题描述】:

我想使用 rlang::eval_tidy() 来评估在 mtcars 命名空间中采用 ... 的函数。

这是一个我想评估的示例函数,从 assertr 借来的。

has_all_names <- function(...){
    check_this <- list(...)
    parent <- parent.frame()
    all(vapply(check_this, 
               function(x) exists(x, where = parent, inherits = FALSE), 
               logical(1)))
}

实现这一点的 base-R 方法是:

fn_base <- function(expr) {
    expr <- substitute(expr)
    eval(expr, envir = mtcars, enclos = parent.frame())
}

但我想使用eval_tidy 来获得其他好处,例如.data 代词。 According to the rlang documentationenexprsubstitute 的 rlang 方式。让我们试试substituteenexpr

fn_rlang_substi <- function(expr) {
    expr <- substitute(expr)
    rlang::eval_tidy(expr, mtcars, parent.frame())
}

fn_rlang_enexpr <- function(expr) {
    expr <- rlang::enexpr(expr)
    rlang::eval_tidy(expr, mtcars, parent.frame())
}

fn_base(has_all_names("cyl", "mpg"))          # TRUE
fn_rlang_substi(has_all_names("cyl", "mpg"))  # FALSE
fn_rlang_enexpr(has_all_names("cyl", "mpg"))  # FALSE

发生了什么事? eval_tidy 有什么不同?

我知道 rlang 具有处理 ... 的功能,但在解决这个问题时,我不想修改 has_all_names。 (用户应该能够提供以... 作为参数的任意函数。)

【问题讨论】:

  • 我会更改您的问题的标题,因为它与点无关。

标签: r rlang tidyeval


【解决方案1】:

您需要inherits = TRUE 进行存在检查,因为eval_tidy() 将屏蔽数据安装在上一级。

【讨论】:

  • 我认为inherits = TRUE 不适合这里,因为我不希望代码搜索完整的环境堆栈。 (has_all_names 专门检查父环境中的对象,而不是任何其他对象。)有没有好方法可以使用parent.framesys.frame 来专门访问数据掩码?
  • 访问数据掩码的方式是parent$.top_env$.data。这与我原来的问题有点不同,但解决了问题。
  • 注意 .top_env 不是公共 API 的一部分,因此可能会使您的代码变得脆弱,尽管没有计划删除它。
猜你喜欢
  • 1970-01-01
  • 2020-07-12
  • 2011-07-04
  • 2010-10-14
  • 2012-10-25
  • 2020-12-15
  • 2016-08-27
  • 2011-01-25
  • 1970-01-01
相关资源
最近更新 更多