I'm implementing an S4 class that contains a data.table
, and attempting to implement [
subsetting of the object (as described here) such that it also subsets the data.table
. For example (defining just i
subsetting):
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)
At this point, subsetting with a numeric vector (s[1:2]
) works as desired (it subsets the data.table
in the slot). However, I'd like to add the ability to subset using an expression. This works for the data.table
itself:
s@dt[b == "x"]
# a b
# 1: 1 x
# 2: 2 x
But not for the S4 [
method:
s[b == "x"]
# Error: object 'b' not found
The problem appears to be that arguments in the signature of the S4 method are not evaluated using R's traditional lazy evaluation- see here:
All arguments in the signature of the generic function will be evaluated when the function is called, rather than using the traditional lazy evaluation rules of S. Therefore, it's important to exclude from the signature any arguments that need to be dealt with symbolically (such as the first argument to function substitute).
This explains why it doesn't work, but not how one can implement this kind of subsetting, since i
and j
are included in the signature of the generic. Is there any way to have the i
argument not be evaluated immediately?