Why doesn't it work with S4 objects that have the as.list.default method?

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 )) 
+5
source share
1 answer

On the help page ?Methods you can find a workable strategy

 #same .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 )) #different as.list.MyClass <-function(x) { lapply(seq_along(x), function(i) x[i]) } setMethod("as.list", "MyClass", as.list.MyClass) #test myobj <- .MyClass(a=1:4, b=letters[1:4]) lapply(myobj, function(i) rep( i@b , i@a )) # [[1]] # [1] "a" # # [[2]] # [1] "b" "b" # # [[3]] # [1] "c" "c" "c" # # [[4]] # [1] "d" "d" "d" "d" 
+4
source

Source: https://habr.com/ru/post/1203546/


All Articles