R’s building blocks

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

Get to the substance - R functions of object inspection

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.ex

Now 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 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