seth127
seth127

Reputation: 2724

In R, does "integer" type inherit from "numeric" type or not?

I'm trying to check the input I'm getting from a user to make sure it's the correct type. In this case, I'm fine with either integer or double as long as it's some kind of number.

I'm using checkmate::check_class() like so with the following results:

> checkmate::check_class(4, "numeric")
[1] TRUE
> checkmate::check_class(as.integer(4), "numeric")
[1] "Must inherit from class 'numeric', but has class 'integer'"

My confusion is because numerous sources on the internet (notably this one from Hadley, in section 12.3.1) appear to be saying that both integer and double do in fact inherit from numeric. So why does this fail?

Sidenote: check_class() says it uses inherits() under the hood so I tried using it explicitly and got the same results.

> inherits(4, "numeric")
[1] TRUE
> inherits(as.integer(4), "integer")
[1] TRUE
> inherits(as.integer(4), "numeric")
[1] FALSE

Thanks in advance for any help and clarification.

Upvotes: 1

Views: 337

Answers (1)

NelsonGon
NelsonGon

Reputation: 13309

This is really to do with the difference between mode and class. When you use as.integer(4), you're explicitly creating an object of class integer. inherits checks class inheritance and therefore inherits(as.integer(4),"numeric") will return FALSE because it is not class numeric.

as.integer(4) is still a numeric object but R's inherits checks only classes not modes which is unlike what you would have expected in terms of inheritance.

inherits indicates whether its first argument inherits from any of the classes specified in the what argument. If which is TRUE then an integer vector of the same length as what is returned. Each element indicates the position in the class(x) matched by the element of what; zero indicates no match. If which is FALSE then TRUE is returned by inherits if any of the names in what match with any class.

Now, looking at the source code of checkmate::check_class, it is essentially doing the same thing(checking inheritance of class not mode):

function (x, classes, ordered = FALSE, null.ok = FALSE) 
{
    qassert(classes, "S+")
    qassert(ordered, "B1")
    qassert(null.ok, "B1")
    if (is.null(x) && null.ok) 
        return(TRUE)
    ord = inherits(x, classes, TRUE)
    w = wf(ord == 0L)
    if (length(w) > 0L) {
        cl = class(x)
        return(sprintf("Must inherit from class '%s', but has class%s '%s'", 
            classes[w], if (length(cl) > 1L) "es" else "", 
            paste0(cl, collapse = "','")))
    }

Why does the first work?

Use checkmate::check_class(4,"numeric"), it correctly returns TRUE because:

 class(4)
[1] "numeric"

I think inheritance here is not used in the way you might have expected because it seems to stop at "one level"(just the class and not mode):

mode(as.integer(4))
[1] "numeric"

Upvotes: 1

Related Questions