Suppose I have a vector-like class S4:
.MyClass <- setClass("MyClass", representation(a="numeric", b="character")) setMethod("[", c("MyClass", "numeric", "missing"), function(x, i, j, ...) { do.call(initialize, c(x, sapply(slotNames(x), function(y) slot(x, y)[i], simplify=FALSE))) }) setMethod("length", "MyClass", function(x) length( x@a ))
And I will say that I also defined methods for as.list and as.list.default :
setGeneric("as.list") setMethod("as.list", "MyClass", function(x) lapply(seq_along(x), function(i) x[i])) setGeneric("as.list.default") setMethod("as.list.default", "MyClass", function(x) lapply(seq_along(x), function(i) x[i]))
Now an object of this class is given, myobj :
myobj <- .MyClass(a=1:4, b=letters[1:4])
When I use lapply , it complains:
> lapply(myobj, function(i) rep( i@b , i@a )) Error in as.list.default(X) : no method for coercing this S4 class to a vector
But if I use as.list.default , the function gives the desired result:
> lapply(as.list.default(myobj), function(i) rep( i@b , i@a )) [[1]] [1] "a" [[2]] [1] "b" "b" ...
Why does lapply not work even though I have defined a method for as.list.default for the class?
Obviously, I can manually define the lapply method for the class, and it will work fine (see below), but I was wondering where the error actually occurs. Why is lapply trying to force my object to a vector, although the function it calls should turn the object into a list?
setGeneric("lapply") setMethod("lapply", c("MyClass", "function"), function(X, FUN, ...) { lapply(as.list(X), FUN, ...) }) lapply(myobj, function(i) rep( i@b , i@a ))