R:基本R函数的整洁度如何?

时间:2019-04-29 04:31:34

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

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

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

我问的原因是,我一直在缓慢而痛苦地将逐渐了解整洁的想法塞入脑海,如果我认为这些强大的方法最终将成为非标准评估的标准,这会让我感到高兴,因为反对永远保持多个队列的古怪的非标准评估方法。

当然,我仍然必须记住,原语本身会使用不同的非标准评估方法,这些方法本身并不是某些通用方法。 (我想说的是对的,尽管泛型函数可以具有原始方法,但原始函数不能(或者至少不是)泛型。是吗?)我对此很满意。

1 个答案:

答案 0 :(得分: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

似乎可以按预期工作,尽管我不确定空白内容如何处理, 它的行为实际上不像缺少的参数:

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

我不知道该行为是错误,功能还是其他原因。