1

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

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

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

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

4

1 回答 1

0

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

首先,如果您阅读 的文档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

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

于 2019-05-02T20:15:18.310 回答