In R, different behavior between `is.list(x)` and `is(x,'list')`

inheritance, r, typechecking, types

Solution

You are mixing S3 and S4 class conventions. `is` and `extends` are for S4 classes but these work with S3 ones because of the way these have been implemented. `inherits` was written for S3 classes and it is not intended to work with S4 objects with full compatibility.

`inherits` effectively compares the result of `class(x)` with the class you specify in the second argument. Hence

> class(data.frame())
[1] "data.frame"

doesn't contain `"list"` anywhere so fails.

Note also this from `?inherits`:

 The analogue of ‘inherits’ for formal classes is ‘is’.  The two
 functions behave consistently with one exception: S4 classes can
 have conditional inheritance, with an explicit test.  In this
 case, ‘is’ will test the condition, but ‘inherits’ ignores all
 conditional superclasses.

Another confusion is with the class of an object and the implementation of that object. Yes a data frame is a list as `is.list()` tells us, but in R's S3 class world, `data.frame()` is of class `"data.frame"` not `"list"`.

As for `is(data.frame(),'list')`, well it isn't of that specific class `"list"` hence the `FALSE`. What `is(data.frame())` does is documented in `?is`

Summary of Functions:

     ‘is’: With two arguments, tests whether ‘object’ can be treated as
          from ‘class2’.

          With one argument, returns all the super-classes of this
          object's class

Hence `is(data.frame())` is showing the classes that the `"data.frame"` class extends (in the S4 sense, not the S3 sense). This further explains the `extends('data.frame','list')` behaviour as in the S4 world, the `"data.frame"` class does extend the `"list"` class.

Problem

What is the explanation for the following behavior? ``` is.list(data.frame()) ## TRUE is(data.frame(),'list') ## FALSE is(data.frame()) ## "data.frame" "list" "oldClass" "vector" extends('data.frame','list') ## TRUE inherits(data.frame(),'list') ## FALSE ```

Original source