In one way, since in R,
Everything that happens is a function call (John Chambers, part 2),
calls are the basic language objects in R.
cc <- quote( sin(x) )
cc## sin(x)
class(cc)## [1] "call"
Looking closely, calls are made from symbols, here, sin(x) is made from the two symbols sin and x:
length(cc)## [1] 2
c1 <- cc[[1]]; c1## sin
c2 <- cc[[2]]; c2## x
typeof(c1)## [1] "symbol"
str(c2)## symbol x
Since in R,
Everything that exists is an object (John Chambers, part 1),
we want to find out what “kind” of an object we have. The most useful “user-level” function to get an idea about an object is str() for displaying the structure of an R object… It is used very often interactively, to get both a bit of an overview and some details about object’s structure. str() is not meant to be used as tool to be used in other functions, so from a programmeR’s view, the standard functions for object inspectionto use are class() which is “high-level” and typeof() which is low-level. For historical reasons (back compatibility with S / S+), another low-level inspector function is storage.mode() and another higher-level one is mode().
Here, we use them on a somewhat representative collection of R objects (all conveniently put in a list) to see how these R objects, are categorized by the different “inspection” functions.
l.ex <- list(one=1, s1= 1:2, pi=pi, I=1i, let= c("A", "a", "b", ":::"),
fn = mean, fn2 = c, fnSpec = `function`,
n = as.name("Mä"), n2 = quote(x), ex = expression(1+1),
cl = call("round",10), cl2 = quote(sin(x)), formals = formals(lm), arg1 = formals(lm)[[1]])
str(l.ex, vec.len = 16, max.level = 1)## List of 15
## $ one : num 1
## $ s1 : int [1:2] 1 2
## $ pi : num 3.14
## $ I : cplx 0+1i
## $ let : chr [1:4] "A" "a" "b" ":::"
## $ fn :function (x, ...)
## $ fn2 :function (..., recursive = FALSE)
## $ fnSpec :.Primitive("function")
## $ n : symbol Mä
## $ n2 : symbol x
## $ ex : expression(1 + 1)
## $ cl : language round(10)
## $ cl2 : language sin(x)
## $ formals:Dotted pair list of 14
## $ arg1 : symbol
myShow <- function(x, max.length= 1000L) {
r <- tryCatch(format(x), error=function(e)e)
r <- if(inherits(r, "error"))
tryCatch(as.character(x), error=function(e)e)
else paste(r, collapse=" ")
r <- if(inherits(r, "error"))
tryCatch(capture.output(x), error=function(e)e)
else paste(r, collapse=" ")
substr(r, 1L, max.length)
}
cbind(show = sapply(l.ex, myShow, max.length = 16),
typeof = sapply(l.ex, typeof),
st.mode = sapply(l.ex, storage.mode),
mode = sapply(l.ex, mode),
class = sapply(l.ex, class)) -> tab.exNow instead of printing this directly - which is readable and nice already, let’s be “advanced” and use a knitr package feature to produce “raw markdown” tables:
knitr::kable(tab.ex, format="pandoc")| show | typeof | st.mode | mode | class | |
|---|---|---|---|---|---|
| one | 1 | double | double | numeric | numeric |
| s1 | 1 2 | integer | integer | numeric | integer |
| pi | 3.141593 | double | double | numeric | numeric |
| I | 0+1i | complex | complex | complex | complex |
| let | A a b ::: | character | character | character | character |
| fn | function (x, … | closure | function | function | function |
| fn2 | .Primitive(“c”) | builtin | function | function | function |
| fnSpec | .Primitive(“func | special | function | function | function |
| n | Mä | symbol | symbol | name | name |
| n2 | x | symbol | symbol | name | name |
| ex | expression(1 + 1 | expression | expression | expression | expression |
| cl | round(10) | language | language | call | call |
| cl2 | sin(x) | language | language | call | call |
| formals | qr TRUE FAL | pairlist | pairlist | pairlist | pairlist |
| arg1 | symbol | symbol | name | name |
Note: The source of this document is MM’s /sfs/u/maechler/R/MM/MISC/type-mode-class.Rmd