对S4方法参数的延迟评估

时间:2014-03-23 15:46:15

标签: r oop data.table subset s4

我实现了一个包含data.table的S4类,并尝试实现对象的[子集(如here所述),这样它也会对{ {1}}。例如(仅定义data.table子集):

i

此时,使用数字向量(library(data.table) .SuperDataTable <- setClass("SuperDataTable", representation(dt="data.table")) setMethod("[", c("SuperDataTable", "ANY", "missing", "ANY"), function(x, i, j, ..., drop=TRUE) { initialize(x, dt=x@dt[i]) }) d = data.table(a=1:4, b=rep(c("x", "y"), each=2)) s = new("SuperDataTable", dt=d) )进行子集化可以根据需要工作(它会对插槽中的s[1:2]进行子集化)。但是,我想使用表达式添加子集功能。这适用于data.table本身:

data.table

但不适用于S4 s@dt[b == "x"] # a b # 1: 1 x # 2: 2 x 方法:

[

问题似乎是,使用R的传统惰性评估不会评估S4方法签名中的参数 - 请参阅here

  

泛型函数签名中的所有参数都是   在调用函数时评估,而不是使用   S的传统懒惰评价规则因此,它很重要   从签名中排除需要处理的任何参数   象征性地(例如功能替代的第一个参数)。

这解释了为什么它不起作用,而不是 如何实现这种子集化的原因,因为s[b == "x"] # Error: object 'b' not found i包含在签名中通用的。有没有办法立即评估j参数而不是

1 个答案:

答案 0 :(得分:1)

你可能对此不太满意。来自R developer notes

  

通用函数的签名中出现的参数将立即进行评估   叫做;因此,任何需要利用懒惰评估的论点都不得参与其中   签名。这些通常是字面处理的参数,通常通过substitute()函数处理。   例如,如果有人想将substitute()本身变成泛型,那么第一个参数expr,   不会出现在签名中,因为它不能被评估,而是被视为文字。

此外,由于方法缓存,

  

如上所述评估完整签名中的所有参数,而不仅仅是活动的   那些。否则,在特殊情况下,函数的行为可能会改变一个   缓存另一种方法时的方法,非常不受欢迎。

我会按照data.table包编写器中的示例来使用S3对象(参见source codeR/data.table.R的第304行)。您的S3对象仍然可以创建和操作下面的S4对象,以维护半静态类型功能。

我们不能非常聪明:

 ‘[’ is a primitive function;  methods can be defined, but the generic function is implicit, and cannot be changed.

定义S3和S4方法将调度S3方法,这使得我们应该能够绕过S4调用并手动调度它,但不幸的是,参数评估仍然会发生!你可以通过借用plyr::.来接近,它会给你如下语法:

s <- new('SuperDataTable', dt = as.data.table(iris))
s[.(Sepal.Length > 4), 2]

不理想,但比其他任何东西都要近。