Ответ 1
(Это исправлено, чтобы быть ближе к предыдущему удаленному ответу, используя slotName
и slot
вместо того, чтобы полагаться на attributes
). Мы могли бы написать функцию, которая проверяет, является ли экземпляр объектом S4, и если он извлекает все слоты в виде списка и рекурсирует
f = function(x) {
if (isS4(x)) {
nms <- slotNames(x)
names(nms) <- nms
lapply(lapply(nms, slot, object=x), f)
} else x
}
а затем
A = setClass("A", representation(x="numeric"))
B = setClass("B", representation(a="A", b="numeric"))
f(B())
чтобы получить простой старый список, который мы могли бы использовать в любых целях.
$a
$a$x
numeric(0)
$a$class
[1] "A"
attr(,"package")
[1] ".GlobalEnv"
$b
numeric(0)
$class
[1] "B"
attr(,"package")
[1] ".GlobalEnv"
f
может потребоваться улучшить, например, для обработки значений NULL или классов S4, сделанных из классов S3, через setOldClass
. Код validObject
был бы моим выбором мест для поиска более полного обхода.
Обобщение может сделать посетителя по строкам
visitLeavesWith <-
function(object, FUN, ...)
{
f = function(x) {
if (isS4(x)) {
slots <- setNames(slotNames(x), slotNames(x))
lapply(lapply(slots, slot, object=x), f)
} else FUN(x, ...)
}
f(object)
}
например.
visitLeavesWith(B(), length)