18.6 Specialised data structures

  • Pairlists
  • Missing arguments
  • Expression vectors

18.6.1 Pairlists

  • Pairlists are a remnant of R’s past and have been replaced by lists almost everywhere.
  • The only place you are likely to see pairlists in R is when working with calls to the function, as the formal arguments to a function are stored in a pairlist:
f <- expr(function(x, y = 10) x + y)
args <- f[[2]]
args
#> $x
#> 
#> 
#> $y
#> [1] 10
typeof(args)
#> [1] "pairlist"
  • Fortunately, whenever you encounter a pairlist, you can treat it just like a regular list:
pl <- pairlist(x = 1, y = 2)
length(pl)
#> [1] 2
pl$x
#> [1] 1

18.6.2 Missing arguments

  • Empty symbols
  • To create an empty symbol, you need to use missing_arg() or expr().
missing_arg()
typeof(missing_arg())
#> [1] "symbol"
  • Empty symbols don’t print anything.
    • To check, we need to use rlang::is_missing()
is_missing(missing_arg())
#> [1] TRUE
  • These are usually present in function formals:
f <- expr(function(x, y = 10) x + y)

args <- f[[2]]


is_missing(args[[1]])
#> [1] TRUE

18.6.3 Expression vectors

  • An expression vector is just a list of expressions.
    • The only difference is that calling eval() on an expression evaluates each individual expression.
    • Instead, it might be more advantageous to use a list of expressions.
  • Expression vectors are only produced by two base functions: expression() and parse():
exp1 <- parse(text = c(" 
x <- 4
x
"))
exp1
#> expression(x <- 4, x)
exp2 <- expression(x <- 4, x)
exp2
#> expression(x <- 4, x)
typeof(exp1)
#> [1] "expression"
typeof(exp2)
#> [1] "expression"
  • Like calls and pairlists, expression vectors behave like lists:
length(exp1)
#> [1] 2
exp1[[1]]
#> x <- 4