I have some custom classes, for example:
setClass("foo", slots = c(mat = "matrix"))
I want to handle how a list of foo
objects are 'unlisted'.
mat <- matrix(rnorm(16), 4)
foo <- new("foo", mat = mat)
unlist(list(foo))
I thought perhaps creating methods for c
(which I thought was used but perhaps incorrectly) and unlist
would solve the problem.
S3 version
#' @export
unlist <- function(x, ...) UseMethod("unlist", x)
#' @export
unlist.default <- base::unlist
#' @method unlist foo
#' @export
unlist.foo <- function(x, ...){
print("called foo unlist")
}
S4 version
#' @export
setMethod("unlist",
signature = "foo",
function(x, recursive = TRUE, use.names = TRUE){
print("call foo unlist")
})
c
function
#' @export
setMethod("c",
signature = "foo",
function(x, ..., recursive = FALSE){
print("called foo c")
})
But I only see the confirmation message when I use c
directly:
c(foo)
[1] "called foo c"
The unlist
just returns the same object with no print message
unlist(list(foo))
[[1]]
An object of class "foo"
Slot "mat":
[,1] [,2] [,3] [,4]
[1,] 0.6711541 -0.2783441 -0.4707375 -0.23060105
[2,] 0.7408401 0.4076826 2.2757187 -0.48547413
[3,] 1.8640581 0.3610619 -0.4632473 -0.06498348
[4,] -0.5595930 0.6679157 -0.8142456 0.27499963
If I call unlist(foo)
then I get the print message but I need to apply it on a list of the foo
objects. Any thoughts on how I can have unlist deal with custom classes within a list?
Ultimately I want the following to return TRUE
:
all.equal(unlist(list(foo)), unlist(list(mat)))
I am afraid this is not possible. unlist
determines the type of its output based on types of individual elements of the list it gets. If all elements are atomic, like in case the only element is foo
(a matrix), it does something to its argument -- coerces arguments to common atomic vector (there is only one) and forgets most of its attributes (e.g. dimensions). However, it does not treat S4 objects (like foo
), that happen to be based on atomic vectors, as atomic vectors: these S4 objects will be hence left intact in the result, and the result will be of type list. So calling unlist
on list(foo)
returns list(foo)
. The behavior is implemented in C (do_unlist
in bind.c
) and seems to me to be in line with the documentation.
To mimick the desired behavior in a subset of possible usages of unlist
, one could probably implement a new class for a list of foo
objects, define list
for foo
, and then define a new unlist
for this list-of-foo class to behave similarly to how the default C implementation of unlist behaves on a list of atomic vectors (I haven't tried).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With