Reputation: 2724
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
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 class
es not mode
s 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