【问题标题】:R: Tidy eval for base R functions?R:基本 R 函数的整洁评估?
【发布时间】:2019-09-17 16:51:38
【问题描述】:

我之前问过一个相关的问题,但我认为这以一种更有趣的方式构建了它。

如果一个基本 R 函数是通用的,并且有一个或多个使用“标准”非标准评估的参数,那么提供一种“整洁”的方法是否可行,如果是这样,是否明智?可用于这些论点的评估技术?我的形象是一些概念上标准的包装器,可以使用元编程技术为每个单独的功能量身定制。它仅适用于对当前具有非标准评估的参数的评估,并且可能仅适用于那些对引用类型进行非标准评估的参数,以便所有当前方法在通过 NextMethod() 进行参数匹配和构造后仍然可用,或者任何其他方法等效于 S4、S6 等。

我问的原因是,我一直在缓慢而痛苦地把对 tidy eval 逐渐增加的理解塞进我的脑海,如果我认为这些强大的方法最终会成为非标准评估的标准,我会很高兴,因为反对永远维护多个古怪的非标准评估方法队列。

当然,我仍然必须记住,不同的非标准评估方法将被原语使用,而这些原语本身并不是某些通用的方法。 (我认为我说得对,虽然泛型函数可以有原始方法,但原始函数不能,或者至少不是,泛型。是吗?)我已经接受了。

【问题讨论】:

    标签: r methods metaprogramming tidyeval non-standard-evaluation


    【解决方案1】:

    我做了一些测试试图找出答案, 而且我认为这会非常不一致。

    首先,如果您阅读InternalMethods 的文档,您将看到以下内容:

    以下原始函数和内部函数是通用的,即您可以为它们编写方法

    所以你可以拥有通用的原始函数。

    这是我的一些测试,尽管我怀疑它们是否详尽。

    library(rlang)
    
    setClass("Foo", list(x="numeric"))
    foo <- new("Foo", x=0)
    

    首先我尝试定义一个$ 方法,它已经为列表和数据框使用引号:

    setMethod("$", signature(x="Foo"), function(x, name) {
      enquo(name)
    })
    
    foo$x
    <quosure>
    expr: ^"x"
    env:  empty
    

    由于某种原因,我们定义的泛型自动将name 更改为字符, 但也许你可以简单地使用sym 然后继续。

    然后我想看看包含省略号的泛型会发生什么:

    setMethod("predict", signature(object="Foo"), function(object, ...) {
      enquos(...)
    })
    
    predict(foo, bar, baz=bak)
    <list_of<quosure>>
    
    [[1]]
    <quosure>
    expr: ^bar
    env:  global
    
    $baz
    <quosure>
    expr: ^bak
    env:  global
    

    没有惊喜(?)

    然后我尝试定义[,它有几个形式参数和...

    setMethod("[", signature(x="Foo"), function(x, i, j, ..., drop=TRUE) {
      enquos(i, j, ...)
    })
    
    foo[bar, , baz, bak]
    <list_of<quosure>>
    
    [[1]]
    <quosure>
    expr: ^bar
    env:  global
    
    [[2]]
    <quosure>
    expr: ^
    env:  empty
    
    [[3]]
    <quosure>
    expr: ^baz
    env:  global
    
    [[4]]
    <quosure>
    expr: ^bak
    env:  global
    

    似乎按预期工作,虽然我不确定如何处理空的 quosure, 它的行为并不像缺少参数:

    f <- function(x) {
      print(missing(x))
      ff <- function(xx) { missing(xx) }
      eval_tidy(ff(!!enquo(x)))
    }
    
    f()
    [1] TRUE
    [1] FALSE
    

    最后我尝试在[ 方法中添加一个形式参数:

    setMethod("[", signature(x="Foo"), function(x, i, j, k, ..., drop=TRUE) {
      enquos(i, j, k, ...)
    })
    
    foo[bar, , baz, bak]
    <list_of<quosure>>
    
    [[1]]
    <quosure>
    expr: ^i
    env:  000001FCA36865F0
    
    [[2]]
    <quosure>
    expr: ^j
    env:  000001FCA36865F0
    
    [[3]]
    <quosure>
    expr: ^baz
    env:  global
    
    [[4]]
    <quosure>
    expr: ^bak
    env:  global
    

    而且我不知道这种行为是错误还是功能或其他什么。

    【讨论】:

      猜你喜欢
      • 2021-02-25
      • 1970-01-01
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 2020-04-28
      • 2015-04-22
      • 2020-11-29
      相关资源
      最近更新 更多