Search code examples
rgenericstypesr-s3

Get list of datatypes with S3 generic function


I try to write a function where I can throw in a abitrary number of objects and get a list of the datatypes of that objects. This is a personal task to learn S3 Generics.

What I have done so far is:

myTypes <- function(x, ...) {
  dots <- list(...)
  return (as.list(apply(dots, 1, myType)))
}

myType <- function(x){
  UseMethod("myType")
}

myType.numeric <- function(x){
  if(is.numeric(x)) "Type: numberic"
}

myType.data.frame <- function(x){
  if(is.data.frame(x)) "Type: dataframe"
}

The error occurs e.g. when I call

x <- 1
y <- 3

myTypes(x,y)

I always get the error: "Error in apply(dots, 1, myType) : dim(X) must have a positive length" and I am not sure what is wrong. Could anyone help me here? Since I am totally new to R I maybe doing something basically wrong.


Solution

  • The first argument of apply must be a matrix-like object (i.e., a matrix, array or data.frame). Otherwise you get this error:

    apply(1, 1, mean)
    #Error in apply(1, 1, mean) : dim(X) must have a positive length
    

    You are passing a list to apply, which can't work because you tell apply to apply the function along the first dimension and a list doesn't have dimensions.

    You probably want to use lapply and not apply:

    myTypes <- function( ...) {
      dots <- list(...)
      lapply(dots, myType)
    }
    
    x <- 1
    y <- 3
    
    myTypes(x,y)
    #[[1]]
    #[1] "Type: numberic"
    #
    #[[2]]
    #[1] "Type: numberic"
    

    Of course, it seems more useful, to simply return the class:

    myTypes <- function(...) {
      dots <- list(...)
      lapply(dots, class)
    }
    
    myTypes(x,y)
    #[[1]]
    #[1] "numeric"
    #
    #[[2]]
    #[1] "numeric"
    

    Btw., if you use S3 method dispatch, you don't have to test the class inside the method because a method is only dispatched if the object has the corresponding class.