为什么不对具有as.list.default方法的S4对象进行lapply工作?

Wil*_*son 5 r class lapply s4

假设我有一个类似矢量的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))
Run Code Online (Sandbox Code Playgroud)

说我还定义方法as.listas.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]))
Run Code Online (Sandbox Code Playgroud)

现在给出这个类的对象,myobj:

myobj <- .MyClass(a=1:4, b=letters[1:4])
Run Code Online (Sandbox Code Playgroud)

当我使用时lapply,它会抱怨:

> 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
Run Code Online (Sandbox Code Playgroud)

但是如果我使用as.list.default,该函数会提供所需的输出:

> lapply(as.list.default(myobj), function(i) rep(i@b, i@a))
[[1]]
[1] "a"

[[2]]
[1] "b" "b"
...
Run Code Online (Sandbox Code Playgroud)

lapply即使我已经as.list.default为类定义了一个方法,为什么不起作用?

显然我可以手动lapply为类定义一个方法,它可以正常工作(下面),但我想知道实际遇到错误的位置.为什么lapply尝试将我的对象强制转换为向量,即使它调用的函数应该将对象转换为列表?

setGeneric("lapply")
setMethod("lapply", c("MyClass", "function"), function(X, FUN, ...) {
  lapply(as.list(X), FUN, ...)
})
lapply(myobj, function(i) rep(i@b, i@a))
Run Code Online (Sandbox Code Playgroud)

MrF*_*ick 4

?Methods帮助页面来看,一个可行的策略似乎是

#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"
Run Code Online (Sandbox Code Playgroud)

  • @agstudy 那么我是否误解了“?Methods”帮助页面?或者它是错误的?(我同意让“lapply”工作并不需要,但这似乎只是最佳实践。) (3认同)