【发布时间】:2014-04-30 20:20:28
【问题描述】:
我正在实现一个包含 data.table 的 S4 类,并尝试实现对象的 [ 子集(如 here 所述),以便它也子集 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 本身:
s@dt[b == "x"]
# a b
# 1: 1 x
# 2: 2 x
但不适用于 S4 [ 方法:
s[b == "x"]
# Error: object 'b' not found
问题似乎是 S4 方法签名中的参数没有使用 R 的传统惰性求值进行求值 - 请参阅 here:
泛型函数签名中的所有参数都是 在调用函数时进行评估,而不是使用 S 的传统惰性求值规则。因此,重要的是 从签名中排除任何需要处理的参数 象征性地(例如函数替换的第一个参数)。
这解释了为什么它不起作用,但不是可以如何实现这种子集,因为i 和j 包含在泛型的签名中。有没有办法让i 参数不立即被评估?
【问题讨论】:
-
我想我很困惑。我通常认为初始化步骤是
new操作的一部分,而不是提取操作的一部分。 -
@IShouldBuyABoat
initialization的使用来自this suggestion(也链接到上面),因为initialization是一个复制构造函数。如果您想用x@dt = x@dt[i]; return(x)替换它,您可以:它与上述问题无关。 -
如果 R 不知道参数的类别,它如何确定调用什么方法?
-
@hadley:如果该参数的签名是
ANY,可以想象它会起作用,因此它不需要知道参数的类别(尽管我知道它不需要) t)。
标签: r oop data.table subset s4